update_client_unittest.cc 188 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <memory>
  5. #include <tuple>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/containers/flat_map.h"
  9. #include "base/files/file_path.h"
  10. #include "base/files/file_util.h"
  11. #include "base/location.h"
  12. #include "base/memory/ref_counted.h"
  13. #include "base/path_service.h"
  14. #include "base/run_loop.h"
  15. #include "base/task/task_traits.h"
  16. #include "base/task/thread_pool.h"
  17. #include "base/test/scoped_path_override.h"
  18. #include "base/test/task_environment.h"
  19. #include "base/threading/thread_task_runner_handle.h"
  20. #include "base/values.h"
  21. #include "base/version.h"
  22. #include "build/build_config.h"
  23. #include "components/crx_file/crx_verifier.h"
  24. #include "components/prefs/testing_pref_service.h"
  25. #include "components/update_client/component_unpacker.h"
  26. #include "components/update_client/crx_downloader_factory.h"
  27. #include "components/update_client/crx_update_item.h"
  28. #include "components/update_client/network.h"
  29. #include "components/update_client/patcher.h"
  30. #include "components/update_client/persisted_data.h"
  31. #include "components/update_client/ping_manager.h"
  32. #include "components/update_client/protocol_handler.h"
  33. #include "components/update_client/test_configurator.h"
  34. #include "components/update_client/test_installer.h"
  35. #include "components/update_client/unzipper.h"
  36. #include "components/update_client/update_checker.h"
  37. #include "components/update_client/update_client_errors.h"
  38. #include "components/update_client/update_client_internal.h"
  39. #include "components/update_client/update_engine.h"
  40. #include "testing/gmock/include/gmock/gmock.h"
  41. #include "testing/gtest/include/gtest/gtest.h"
  42. #include "third_party/abseil-cpp/absl/types/optional.h"
  43. #include "url/gurl.h"
  44. namespace update_client {
  45. namespace {
  46. using base::FilePath;
  47. // Makes a copy of the file specified by |from_path| in a temporary directory
  48. // and returns the path of the copy. Returns true if successful. Cleans up if
  49. // there was an error creating the copy.
  50. bool MakeTestFile(const FilePath& from_path, FilePath* to_path) {
  51. FilePath temp_dir;
  52. bool result =
  53. CreateNewTempDirectory(FILE_PATH_LITERAL("update_client"), &temp_dir);
  54. if (!result)
  55. return false;
  56. FilePath temp_file;
  57. result = CreateTemporaryFileInDir(temp_dir, &temp_file);
  58. if (!result)
  59. return false;
  60. result = CopyFile(from_path, temp_file);
  61. if (!result) {
  62. base::DeleteFile(temp_file);
  63. return false;
  64. }
  65. *to_path = temp_file;
  66. return true;
  67. }
  68. using Events = UpdateClient::Observer::Events;
  69. class MockObserver : public UpdateClient::Observer {
  70. public:
  71. MOCK_METHOD2(OnEvent, void(Events event, const std::string&));
  72. };
  73. class MockActionHandler : public ActionHandler {
  74. public:
  75. MockActionHandler() = default;
  76. MockActionHandler(const MockActionHandler&) = delete;
  77. MockActionHandler& operator=(const MockActionHandler&) = delete;
  78. MOCK_METHOD3(Handle,
  79. void(const base::FilePath&, const std::string&, Callback));
  80. private:
  81. ~MockActionHandler() override = default;
  82. };
  83. class MockCrxStateChangeReceiver
  84. : public base::RefCountedThreadSafe<MockCrxStateChangeReceiver> {
  85. public:
  86. MOCK_METHOD(void, Receive, (CrxUpdateItem));
  87. private:
  88. friend class base::RefCountedThreadSafe<MockCrxStateChangeReceiver>;
  89. ~MockCrxStateChangeReceiver() = default;
  90. };
  91. class MockCrxDownloaderFactory : public CrxDownloaderFactory {
  92. public:
  93. explicit MockCrxDownloaderFactory(scoped_refptr<CrxDownloader> crx_downloader)
  94. : crx_downloader_(crx_downloader) {}
  95. private:
  96. ~MockCrxDownloaderFactory() override = default;
  97. // Overrides for CrxDownloaderFactory.
  98. scoped_refptr<CrxDownloader> MakeCrxDownloader(
  99. bool /* background_download_enabled */) const override {
  100. return crx_downloader_;
  101. }
  102. scoped_refptr<CrxDownloader> crx_downloader_;
  103. };
  104. } // namespace
  105. using ::testing::_;
  106. using ::testing::AnyNumber;
  107. using ::testing::AtLeast;
  108. using ::testing::DoAll;
  109. using ::testing::InSequence;
  110. using ::testing::Invoke;
  111. using ::testing::Mock;
  112. using ::testing::Return;
  113. using ::testing::Unused;
  114. using std::string;
  115. class MockPingManagerImpl : public PingManager {
  116. public:
  117. struct PingData {
  118. std::string id;
  119. base::Version previous_version;
  120. base::Version next_version;
  121. ErrorCategory error_category = ErrorCategory::kNone;
  122. int error_code = 0;
  123. int extra_code1 = 0;
  124. ErrorCategory diff_error_category = ErrorCategory::kNone;
  125. int diff_error_code = 0;
  126. bool diff_update_failed = false;
  127. };
  128. explicit MockPingManagerImpl(scoped_refptr<Configurator> config);
  129. MockPingManagerImpl(const MockPingManagerImpl&) = delete;
  130. MockPingManagerImpl& operator=(const MockPingManagerImpl&) = delete;
  131. void SendPing(const Component& component,
  132. const PersistedData& metadata,
  133. Callback callback) override;
  134. const std::vector<PingData>& ping_data() const;
  135. const std::vector<base::Value>& events() const;
  136. protected:
  137. ~MockPingManagerImpl() override;
  138. private:
  139. std::vector<PingData> ping_data_;
  140. std::vector<base::Value> events_;
  141. };
  142. MockPingManagerImpl::MockPingManagerImpl(scoped_refptr<Configurator> config)
  143. : PingManager(config) {}
  144. MockPingManagerImpl::~MockPingManagerImpl() = default;
  145. void MockPingManagerImpl::SendPing(const Component& component,
  146. const PersistedData& metadata,
  147. Callback callback) {
  148. PingData ping_data;
  149. ping_data.id = component.id_;
  150. ping_data.previous_version = component.previous_version_;
  151. ping_data.next_version = component.next_version_;
  152. ping_data.error_category = component.error_category_;
  153. ping_data.error_code = component.error_code_;
  154. ping_data.extra_code1 = component.extra_code1_;
  155. ping_data.diff_error_category = component.diff_error_category_;
  156. ping_data.diff_error_code = component.diff_error_code_;
  157. ping_data.diff_update_failed = component.diff_update_failed();
  158. ping_data_.push_back(ping_data);
  159. events_ = component.GetEvents();
  160. std::move(callback).Run(0, "");
  161. }
  162. const std::vector<MockPingManagerImpl::PingData>&
  163. MockPingManagerImpl::ping_data() const {
  164. return ping_data_;
  165. }
  166. const std::vector<base::Value>& MockPingManagerImpl::events() const {
  167. return events_;
  168. }
  169. class UpdateClientTest : public testing::Test {
  170. public:
  171. UpdateClientTest(const UpdateClientTest&) = delete;
  172. UpdateClientTest& operator=(const UpdateClientTest&) = delete;
  173. protected:
  174. UpdateClientTest();
  175. ~UpdateClientTest() override = default;
  176. void RunThreads();
  177. // Returns the full path to a test file.
  178. static base::FilePath TestFilePath(const char* file);
  179. scoped_refptr<update_client::TestConfigurator> config() { return config_; }
  180. update_client::PersistedData* metadata() { return metadata_.get(); }
  181. base::OnceClosure quit_closure() { return runloop_.QuitClosure(); }
  182. // Injects the CrxDownloaderFactory in the test fixture.
  183. template <typename MockCrxDownloaderT>
  184. void SetMockCrxDownloader() {
  185. config()->SetCrxDownloaderFactory(
  186. base::MakeRefCounted<MockCrxDownloaderFactory>(
  187. base::MakeRefCounted<MockCrxDownloaderT>()));
  188. }
  189. private:
  190. static constexpr int kNumWorkerThreads_ = 2;
  191. base::test::TaskEnvironment task_environment_;
  192. base::RunLoop runloop_;
  193. std::unique_ptr<TestingPrefServiceSimple> pref_ =
  194. std::make_unique<TestingPrefServiceSimple>();
  195. scoped_refptr<update_client::TestConfigurator> config_ =
  196. base::MakeRefCounted<TestConfigurator>(pref_.get());
  197. std::unique_ptr<update_client::PersistedData> metadata_ =
  198. std::make_unique<PersistedData>(pref_.get(), nullptr);
  199. };
  200. constexpr int UpdateClientTest::kNumWorkerThreads_;
  201. UpdateClientTest::UpdateClientTest() {
  202. PersistedData::RegisterPrefs(pref_->registry());
  203. }
  204. void UpdateClientTest::RunThreads() {
  205. runloop_.Run();
  206. task_environment_.RunUntilIdle();
  207. }
  208. base::FilePath UpdateClientTest::TestFilePath(const char* file) {
  209. base::FilePath path;
  210. base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
  211. return path.AppendASCII("components")
  212. .AppendASCII("test")
  213. .AppendASCII("data")
  214. .AppendASCII("update_client")
  215. .AppendASCII(file);
  216. }
  217. // Tests the scenario where one update check is done for one CRX. The CRX
  218. // has no update.
  219. TEST_F(UpdateClientTest, OneCrxNoUpdate) {
  220. class DataCallbackMock {
  221. public:
  222. static std::vector<absl::optional<CrxComponent>> Callback(
  223. const std::vector<std::string>& ids) {
  224. CrxComponent crx;
  225. crx.name = "test_jebg";
  226. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  227. crx.version = base::Version("0.9");
  228. crx.installer = base::MakeRefCounted<TestInstaller>();
  229. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  230. std::vector<absl::optional<CrxComponent>> component = {crx};
  231. return component;
  232. }
  233. };
  234. class CompletionCallbackMock {
  235. public:
  236. static void Callback(base::OnceClosure quit_closure, Error error) {
  237. EXPECT_EQ(Error::NONE, error);
  238. std::move(quit_closure).Run();
  239. }
  240. };
  241. class MockUpdateChecker : public UpdateChecker {
  242. public:
  243. static std::unique_ptr<UpdateChecker> Create(
  244. scoped_refptr<Configurator> config,
  245. PersistedData* metadata) {
  246. return std::make_unique<MockUpdateChecker>();
  247. }
  248. void CheckForUpdates(
  249. scoped_refptr<UpdateContext> context,
  250. const base::flat_map<std::string, std::string>& additional_attributes,
  251. UpdateCheckCallback update_check_callback) override {
  252. EXPECT_FALSE(context->session_id.empty());
  253. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  254. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  255. EXPECT_EQ(id, context->components_to_check_for_updates.front());
  256. EXPECT_EQ(1u, context->components.count(id));
  257. auto& component = context->components.at(id);
  258. EXPECT_TRUE(component->is_foreground());
  259. ProtocolParser::Result result;
  260. result.extension_id = id;
  261. result.status = "noupdate";
  262. ProtocolParser::Results results;
  263. results.list.push_back(result);
  264. base::ThreadTaskRunnerHandle::Get()->PostTask(
  265. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  266. ErrorCategory::kNone, 0, 0));
  267. }
  268. };
  269. class MockCrxDownloader : public CrxDownloader {
  270. public:
  271. MockCrxDownloader() : CrxDownloader(nullptr) {}
  272. private:
  273. ~MockCrxDownloader() override = default;
  274. void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
  275. };
  276. class MockPingManager : public MockPingManagerImpl {
  277. public:
  278. explicit MockPingManager(scoped_refptr<Configurator> config)
  279. : MockPingManagerImpl(config) {}
  280. protected:
  281. ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
  282. };
  283. SetMockCrxDownloader<MockCrxDownloader>();
  284. scoped_refptr<UpdateClient> update_client =
  285. base::MakeRefCounted<UpdateClientImpl>(
  286. config(), base::MakeRefCounted<MockPingManager>(config()),
  287. &MockUpdateChecker::Create);
  288. MockObserver observer;
  289. {
  290. InSequence seq;
  291. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  292. "jebgalgnebhfojomionfpkfelancnnkf"))
  293. .Times(1);
  294. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_ALREADY_UP_TO_DATE,
  295. "jebgalgnebhfojomionfpkfelancnnkf"))
  296. .Times(1);
  297. }
  298. std::vector<CrxUpdateItem> items;
  299. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  300. EXPECT_CALL(*receiver, Receive(_))
  301. .WillRepeatedly(
  302. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  303. update_client->AddObserver(&observer);
  304. const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"};
  305. update_client->Update(
  306. ids, base::BindOnce(&DataCallbackMock::Callback),
  307. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), true,
  308. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  309. RunThreads();
  310. EXPECT_EQ(2u, items.size());
  311. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  312. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  313. EXPECT_EQ(ComponentState::kUpToDate, items[1].state);
  314. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[1].id.c_str());
  315. update_client->RemoveObserver(&observer);
  316. }
  317. // Tests the scenario where two CRXs are checked for updates. On CRX has
  318. // an update, the other CRX does not.
  319. TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
  320. class DataCallbackMock {
  321. public:
  322. static std::vector<absl::optional<CrxComponent>> Callback(
  323. const std::vector<std::string>& ids) {
  324. CrxComponent crx1;
  325. crx1.name = "test_jebg";
  326. crx1.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  327. crx1.version = base::Version("0.9");
  328. crx1.installer = base::MakeRefCounted<TestInstaller>();
  329. crx1.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  330. CrxComponent crx2;
  331. crx2.name = "test_abag";
  332. crx2.pk_hash.assign(abag_hash, abag_hash + std::size(abag_hash));
  333. crx2.version = base::Version("2.2");
  334. crx2.installer = base::MakeRefCounted<TestInstaller>();
  335. crx2.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  336. return {crx1, crx2};
  337. }
  338. };
  339. class CompletionCallbackMock {
  340. public:
  341. static void Callback(base::OnceClosure quit_closure, Error error) {
  342. EXPECT_EQ(Error::NONE, error);
  343. std::move(quit_closure).Run();
  344. }
  345. };
  346. class MockUpdateChecker : public UpdateChecker {
  347. public:
  348. static std::unique_ptr<UpdateChecker> Create(
  349. scoped_refptr<Configurator> config,
  350. PersistedData* metadata) {
  351. return std::make_unique<MockUpdateChecker>();
  352. }
  353. void CheckForUpdates(
  354. scoped_refptr<UpdateContext> context,
  355. const base::flat_map<std::string, std::string>& additional_attributes,
  356. UpdateCheckCallback update_check_callback) override {
  357. /*
  358. Mock the following response:
  359. <?xml version='1.0' encoding='UTF-8'?>
  360. <response protocol='3.1'>
  361. <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
  362. <updatecheck status='ok'>
  363. <urls>
  364. <url codebase='http://localhost/download/'/>
  365. </urls>
  366. <manifest version='1.0' prodversionmin='11.0.1.0'>
  367. <packages>
  368. <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
  369. hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
  370. a284a7cd8059c3409ce0498'/>
  371. </packages>
  372. </manifest>
  373. </updatecheck>
  374. </app>
  375. <app appid='abagagagagagagagagagagagagagagag'>
  376. <updatecheck status='noupdate'/>
  377. </app>
  378. </response>
  379. */
  380. EXPECT_FALSE(context->session_id.empty());
  381. EXPECT_EQ(2u, context->components_to_check_for_updates.size());
  382. ProtocolParser::Results results;
  383. {
  384. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  385. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  386. EXPECT_EQ(1u, context->components.count(id));
  387. ProtocolParser::Result::Manifest::Package package;
  388. package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
  389. package.hash_sha256 =
  390. "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
  391. ProtocolParser::Result result;
  392. result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf";
  393. result.status = "ok";
  394. result.crx_urls.push_back(GURL("http://localhost/download/"));
  395. result.manifest.version = "1.0";
  396. result.manifest.browser_min_version = "11.0.1.0";
  397. result.manifest.packages.push_back(package);
  398. results.list.push_back(result);
  399. EXPECT_FALSE(context->components.at(id)->is_foreground());
  400. }
  401. {
  402. const std::string id = "abagagagagagagagagagagagagagagag";
  403. EXPECT_EQ(id, context->components_to_check_for_updates[1]);
  404. EXPECT_EQ(1u, context->components.count(id));
  405. ProtocolParser::Result result;
  406. result.extension_id = id;
  407. result.status = "noupdate";
  408. results.list.push_back(result);
  409. EXPECT_FALSE(context->components.at(id)->is_foreground());
  410. }
  411. base::ThreadTaskRunnerHandle::Get()->PostTask(
  412. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  413. ErrorCategory::kNone, 0, 0));
  414. }
  415. };
  416. class MockCrxDownloader : public CrxDownloader {
  417. public:
  418. MockCrxDownloader() : CrxDownloader(nullptr) {}
  419. private:
  420. ~MockCrxDownloader() override = default;
  421. void DoStartDownload(const GURL& url) override {
  422. DownloadMetrics download_metrics;
  423. download_metrics.url = url;
  424. download_metrics.downloader = DownloadMetrics::kNone;
  425. download_metrics.error = 0;
  426. download_metrics.downloaded_bytes = 1843;
  427. download_metrics.total_bytes = 1843;
  428. download_metrics.download_time_ms = 1000;
  429. FilePath path;
  430. EXPECT_TRUE(MakeTestFile(
  431. TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
  432. Result result;
  433. result.error = 0;
  434. result.response = path;
  435. base::ThreadTaskRunnerHandle::Get()->PostTask(
  436. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  437. base::Unretained(this),
  438. download_metrics.downloaded_bytes / 2,
  439. download_metrics.total_bytes));
  440. base::ThreadTaskRunnerHandle::Get()->PostTask(
  441. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  442. base::Unretained(this),
  443. download_metrics.downloaded_bytes,
  444. download_metrics.total_bytes));
  445. base::ThreadTaskRunnerHandle::Get()->PostTask(
  446. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  447. base::Unretained(this), true, result,
  448. download_metrics));
  449. }
  450. };
  451. class MockPingManager : public MockPingManagerImpl {
  452. public:
  453. explicit MockPingManager(scoped_refptr<Configurator> config)
  454. : MockPingManagerImpl(config) {}
  455. protected:
  456. ~MockPingManager() override {
  457. const auto ping_data = MockPingManagerImpl::ping_data();
  458. EXPECT_EQ(1u, ping_data.size());
  459. EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
  460. EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
  461. EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
  462. EXPECT_EQ(0, static_cast<int>(ping_data[0].error_category));
  463. EXPECT_EQ(0, ping_data[0].error_code);
  464. }
  465. };
  466. SetMockCrxDownloader<MockCrxDownloader>();
  467. scoped_refptr<UpdateClient> update_client =
  468. base::MakeRefCounted<UpdateClientImpl>(
  469. config(), base::MakeRefCounted<MockPingManager>(config()),
  470. &MockUpdateChecker::Create);
  471. MockObserver observer;
  472. {
  473. InSequence seq;
  474. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  475. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  476. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  477. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  478. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  479. "jebgalgnebhfojomionfpkfelancnnkf"))
  480. .Times(AtLeast(1));
  481. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
  482. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  483. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
  484. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  485. }
  486. {
  487. InSequence seq;
  488. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  489. "abagagagagagagagagagagagagagagag")).Times(1);
  490. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_ALREADY_UP_TO_DATE,
  491. "abagagagagagagagagagagagagagagag"))
  492. .Times(1);
  493. }
  494. std::vector<CrxUpdateItem> items;
  495. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  496. EXPECT_CALL(*receiver, Receive(_))
  497. .WillRepeatedly(
  498. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  499. update_client->AddObserver(&observer);
  500. const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
  501. "abagagagagagagagagagagagagagagag"};
  502. update_client->Update(
  503. ids, base::BindOnce(&DataCallbackMock::Callback),
  504. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  505. false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  506. RunThreads();
  507. EXPECT_EQ(9u, items.size());
  508. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  509. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  510. EXPECT_EQ(ComponentState::kChecking, items[1].state);
  511. EXPECT_STREQ("abagagagagagagagagagagagagagagag", items[1].id.c_str());
  512. EXPECT_EQ(ComponentState::kCanUpdate, items[2].state);
  513. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str());
  514. EXPECT_EQ(ComponentState::kDownloading, items[3].state);
  515. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str());
  516. EXPECT_EQ(ComponentState::kDownloading, items[4].state);
  517. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str());
  518. EXPECT_EQ(ComponentState::kDownloading, items[5].state);
  519. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[5].id.c_str());
  520. EXPECT_EQ(ComponentState::kUpdating, items[6].state);
  521. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[6].id.c_str());
  522. EXPECT_EQ(ComponentState::kUpdated, items[7].state);
  523. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[7].id.c_str());
  524. EXPECT_EQ(ComponentState::kUpToDate, items[8].state);
  525. EXPECT_STREQ("abagagagagagagagagagagagagagagag", items[8].id.c_str());
  526. std::vector<std::tuple<int64_t, int64_t>> progress_bytes = {
  527. {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {921, 1843},
  528. {1843, 1843}, {1843, 1843}, {1843, 1843}, {-1, -1}};
  529. EXPECT_EQ(items.size(), progress_bytes.size());
  530. for (size_t i{0}; i != items.size(); ++i) {
  531. EXPECT_EQ(items[i].downloaded_bytes, std::get<0>(progress_bytes[i]));
  532. EXPECT_EQ(items[i].total_bytes, std::get<1>(progress_bytes[i]));
  533. }
  534. update_client->RemoveObserver(&observer);
  535. }
  536. // Tests the scenario where two CRXs are checked for updates. One CRX has
  537. // an update but the server ignores the second CRX and returns no response for
  538. // it. The second component gets an |UPDATE_RESPONSE_NOT_FOUND| error and
  539. // transitions to the error state.
  540. TEST_F(UpdateClientTest, TwoCrxUpdateFirstServerIgnoresSecond) {
  541. class DataCallbackMock {
  542. public:
  543. static std::vector<absl::optional<CrxComponent>> Callback(
  544. const std::vector<std::string>& ids) {
  545. CrxComponent crx1;
  546. crx1.name = "test_jebg";
  547. crx1.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  548. crx1.version = base::Version("0.9");
  549. crx1.installer = base::MakeRefCounted<TestInstaller>();
  550. crx1.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  551. CrxComponent crx2;
  552. crx2.name = "test_abag";
  553. crx2.pk_hash.assign(abag_hash, abag_hash + std::size(abag_hash));
  554. crx2.version = base::Version("2.2");
  555. crx2.installer = base::MakeRefCounted<TestInstaller>();
  556. crx2.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  557. return {crx1, crx2};
  558. }
  559. };
  560. class CompletionCallbackMock {
  561. public:
  562. static void Callback(base::OnceClosure quit_closure, Error error) {
  563. EXPECT_EQ(Error::NONE, error);
  564. std::move(quit_closure).Run();
  565. }
  566. };
  567. class MockUpdateChecker : public UpdateChecker {
  568. public:
  569. static std::unique_ptr<UpdateChecker> Create(
  570. scoped_refptr<Configurator> config,
  571. PersistedData* metadata) {
  572. return std::make_unique<MockUpdateChecker>();
  573. }
  574. void CheckForUpdates(
  575. scoped_refptr<UpdateContext> context,
  576. const base::flat_map<std::string, std::string>& additional_attributes,
  577. UpdateCheckCallback update_check_callback) override {
  578. /*
  579. Mock the following response:
  580. <?xml version='1.0' encoding='UTF-8'?>
  581. <response protocol='3.1'>
  582. <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
  583. <updatecheck status='ok'>
  584. <urls>
  585. <url codebase='http://localhost/download/'/>
  586. </urls>
  587. <manifest version='1.0' prodversionmin='11.0.1.0'>
  588. <packages>
  589. <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
  590. hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
  591. a284a7cd8059c3409ce0498'/>
  592. </packages>
  593. </manifest>
  594. </updatecheck>
  595. </app>
  596. </response>
  597. */
  598. EXPECT_FALSE(context->session_id.empty());
  599. EXPECT_EQ(2u, context->components_to_check_for_updates.size());
  600. ProtocolParser::Results results;
  601. {
  602. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  603. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  604. EXPECT_EQ(1u, context->components.count(id));
  605. ProtocolParser::Result::Manifest::Package package;
  606. package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
  607. package.hash_sha256 =
  608. "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
  609. ProtocolParser::Result result;
  610. result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf";
  611. result.status = "ok";
  612. result.crx_urls.push_back(GURL("http://localhost/download/"));
  613. result.manifest.version = "1.0";
  614. result.manifest.browser_min_version = "11.0.1.0";
  615. result.manifest.packages.push_back(package);
  616. results.list.push_back(result);
  617. EXPECT_FALSE(context->components.at(id)->is_foreground());
  618. }
  619. base::ThreadTaskRunnerHandle::Get()->PostTask(
  620. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  621. ErrorCategory::kNone, 0, 0));
  622. }
  623. };
  624. class MockCrxDownloader : public CrxDownloader {
  625. public:
  626. MockCrxDownloader() : CrxDownloader(nullptr) {}
  627. private:
  628. ~MockCrxDownloader() override = default;
  629. void DoStartDownload(const GURL& url) override {
  630. DownloadMetrics download_metrics;
  631. download_metrics.url = url;
  632. download_metrics.downloader = DownloadMetrics::kNone;
  633. download_metrics.error = 0;
  634. download_metrics.downloaded_bytes = 1843;
  635. download_metrics.total_bytes = 1843;
  636. download_metrics.download_time_ms = 1000;
  637. FilePath path;
  638. EXPECT_TRUE(MakeTestFile(
  639. TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
  640. Result result;
  641. result.error = 0;
  642. result.response = path;
  643. base::ThreadTaskRunnerHandle::Get()->PostTask(
  644. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  645. base::Unretained(this),
  646. download_metrics.downloaded_bytes,
  647. download_metrics.total_bytes));
  648. base::ThreadTaskRunnerHandle::Get()->PostTask(
  649. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  650. base::Unretained(this), true, result,
  651. download_metrics));
  652. }
  653. };
  654. class MockPingManager : public MockPingManagerImpl {
  655. public:
  656. explicit MockPingManager(scoped_refptr<Configurator> config)
  657. : MockPingManagerImpl(config) {}
  658. protected:
  659. ~MockPingManager() override {
  660. const auto ping_data = MockPingManagerImpl::ping_data();
  661. EXPECT_EQ(1u, ping_data.size());
  662. EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
  663. EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
  664. EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
  665. EXPECT_EQ(0, static_cast<int>(ping_data[0].error_category));
  666. EXPECT_EQ(0, ping_data[0].error_code);
  667. }
  668. };
  669. SetMockCrxDownloader<MockCrxDownloader>();
  670. scoped_refptr<UpdateClient> update_client =
  671. base::MakeRefCounted<UpdateClientImpl>(
  672. config(), base::MakeRefCounted<MockPingManager>(config()),
  673. &MockUpdateChecker::Create);
  674. MockObserver observer;
  675. {
  676. InSequence seq;
  677. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  678. "jebgalgnebhfojomionfpkfelancnnkf"))
  679. .Times(1);
  680. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  681. "jebgalgnebhfojomionfpkfelancnnkf"))
  682. .Times(1);
  683. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  684. "jebgalgnebhfojomionfpkfelancnnkf"))
  685. .Times(AtLeast(1));
  686. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
  687. "jebgalgnebhfojomionfpkfelancnnkf"))
  688. .Times(1);
  689. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
  690. "jebgalgnebhfojomionfpkfelancnnkf"))
  691. .Times(1);
  692. }
  693. {
  694. InSequence seq;
  695. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  696. "abagagagagagagagagagagagagagagag"))
  697. .Times(1);
  698. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  699. "abagagagagagagagagagagagagagagag"))
  700. .Times(1)
  701. .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
  702. CrxUpdateItem item;
  703. EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
  704. EXPECT_EQ(ComponentState::kUpdateError, item.state);
  705. EXPECT_EQ(5, static_cast<int>(item.error_category));
  706. EXPECT_EQ(-10004, item.error_code);
  707. EXPECT_EQ(0, item.extra_code1);
  708. }));
  709. }
  710. std::vector<CrxUpdateItem> items;
  711. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  712. EXPECT_CALL(*receiver, Receive(_))
  713. .WillRepeatedly(
  714. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  715. update_client->AddObserver(&observer);
  716. const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
  717. "abagagagagagagagagagagagagagagag"};
  718. update_client->Update(
  719. ids, base::BindOnce(&DataCallbackMock::Callback),
  720. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  721. false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  722. RunThreads();
  723. EXPECT_EQ(8u, items.size());
  724. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  725. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  726. EXPECT_EQ(ComponentState::kChecking, items[1].state);
  727. EXPECT_STREQ("abagagagagagagagagagagagagagagag", items[1].id.c_str());
  728. EXPECT_EQ(ComponentState::kCanUpdate, items[2].state);
  729. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str());
  730. EXPECT_EQ(ComponentState::kDownloading, items[3].state);
  731. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str());
  732. EXPECT_EQ(ComponentState::kDownloading, items[4].state);
  733. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str());
  734. EXPECT_EQ(ComponentState::kUpdating, items[5].state);
  735. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[5].id.c_str());
  736. EXPECT_EQ(ComponentState::kUpdated, items[6].state);
  737. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[6].id.c_str());
  738. EXPECT_EQ(ComponentState::kUpdateError, items[7].state);
  739. EXPECT_STREQ("abagagagagagagagagagagagagagagag", items[7].id.c_str());
  740. update_client->RemoveObserver(&observer);
  741. }
  742. // Tests the update check for two CRXs scenario when the second CRX does not
  743. // provide a CrxComponent instance. In this case, the update is handled as
  744. // if only one component were provided as an argument to the |Update| call
  745. // with the exception that the second component still fires an event such as
  746. // |COMPONENT_UPDATE_ERROR|.
  747. TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentData) {
  748. class DataCallbackMock {
  749. public:
  750. static std::vector<absl::optional<CrxComponent>> Callback(
  751. const std::vector<std::string>& ids) {
  752. CrxComponent crx;
  753. crx.name = "test_jebg";
  754. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  755. crx.version = base::Version("0.9");
  756. crx.installer = base::MakeRefCounted<TestInstaller>();
  757. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  758. return {crx, absl::nullopt};
  759. }
  760. };
  761. class CompletionCallbackMock {
  762. public:
  763. static void Callback(base::OnceClosure quit_closure, Error error) {
  764. EXPECT_EQ(Error::NONE, error);
  765. std::move(quit_closure).Run();
  766. }
  767. };
  768. class MockUpdateChecker : public UpdateChecker {
  769. public:
  770. static std::unique_ptr<UpdateChecker> Create(
  771. scoped_refptr<Configurator> config,
  772. PersistedData* metadata) {
  773. return std::make_unique<MockUpdateChecker>();
  774. }
  775. void CheckForUpdates(
  776. scoped_refptr<UpdateContext> context,
  777. const base::flat_map<std::string, std::string>& additional_attributes,
  778. UpdateCheckCallback update_check_callback) override {
  779. /*
  780. Mock the following response:
  781. <?xml version='1.0' encoding='UTF-8'?>
  782. <response protocol='3.1'>
  783. <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
  784. <updatecheck status='ok'>
  785. <urls>
  786. <url codebase='http://localhost/download/'/>
  787. </urls>
  788. <manifest version='1.0' prodversionmin='11.0.1.0'>
  789. <packages>
  790. <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
  791. hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
  792. a284a7cd8059c3409ce0498'/>
  793. </packages>
  794. </manifest>
  795. </updatecheck>
  796. </app>
  797. </response>
  798. */
  799. EXPECT_FALSE(context->session_id.empty());
  800. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  801. ProtocolParser::Results results;
  802. {
  803. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  804. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  805. EXPECT_EQ(1u, context->components.count(id));
  806. ProtocolParser::Result::Manifest::Package package;
  807. package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
  808. package.hash_sha256 =
  809. "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
  810. ProtocolParser::Result result;
  811. result.extension_id = id;
  812. result.status = "ok";
  813. result.crx_urls.push_back(GURL("http://localhost/download/"));
  814. result.manifest.version = "1.0";
  815. result.manifest.browser_min_version = "11.0.1.0";
  816. result.manifest.packages.push_back(package);
  817. results.list.push_back(result);
  818. EXPECT_FALSE(context->components.at(id)->is_foreground());
  819. }
  820. base::ThreadTaskRunnerHandle::Get()->PostTask(
  821. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  822. ErrorCategory::kNone, 0, 0));
  823. }
  824. };
  825. class MockCrxDownloader : public CrxDownloader {
  826. public:
  827. MockCrxDownloader() : CrxDownloader(nullptr) {}
  828. private:
  829. ~MockCrxDownloader() override = default;
  830. void DoStartDownload(const GURL& url) override {
  831. DownloadMetrics download_metrics;
  832. FilePath path;
  833. Result result;
  834. if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") {
  835. download_metrics.url = url;
  836. download_metrics.downloader = DownloadMetrics::kNone;
  837. download_metrics.error = 0;
  838. download_metrics.downloaded_bytes = 1843;
  839. download_metrics.total_bytes = 1843;
  840. download_metrics.download_time_ms = 1000;
  841. EXPECT_TRUE(MakeTestFile(
  842. TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
  843. result.error = 0;
  844. result.response = path;
  845. } else {
  846. NOTREACHED();
  847. }
  848. base::ThreadTaskRunnerHandle::Get()->PostTask(
  849. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  850. base::Unretained(this),
  851. download_metrics.downloaded_bytes,
  852. download_metrics.total_bytes));
  853. base::ThreadTaskRunnerHandle::Get()->PostTask(
  854. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  855. base::Unretained(this), true, result,
  856. download_metrics));
  857. }
  858. };
  859. class MockPingManager : public MockPingManagerImpl {
  860. public:
  861. explicit MockPingManager(scoped_refptr<Configurator> config)
  862. : MockPingManagerImpl(config) {}
  863. protected:
  864. ~MockPingManager() override {
  865. const auto ping_data = MockPingManagerImpl::ping_data();
  866. EXPECT_EQ(1u, ping_data.size());
  867. EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
  868. EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
  869. EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
  870. EXPECT_EQ(0, static_cast<int>(ping_data[0].error_category));
  871. EXPECT_EQ(0, ping_data[0].error_code);
  872. }
  873. };
  874. SetMockCrxDownloader<MockCrxDownloader>();
  875. scoped_refptr<UpdateClient> update_client =
  876. base::MakeRefCounted<UpdateClientImpl>(
  877. config(), base::MakeRefCounted<MockPingManager>(config()),
  878. &MockUpdateChecker::Create);
  879. MockObserver observer;
  880. {
  881. InSequence seq;
  882. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  883. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  884. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  885. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  886. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  887. "jebgalgnebhfojomionfpkfelancnnkf"))
  888. .Times(AtLeast(1));
  889. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
  890. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  891. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
  892. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  893. }
  894. {
  895. InSequence seq;
  896. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  897. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  898. .Times(1);
  899. }
  900. std::vector<CrxUpdateItem> items;
  901. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  902. EXPECT_CALL(*receiver, Receive(_))
  903. .WillRepeatedly(
  904. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  905. update_client->AddObserver(&observer);
  906. const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
  907. "ihfokbkgjpifnbbojhneepfflplebdkc"};
  908. update_client->Update(
  909. ids, base::BindOnce(&DataCallbackMock::Callback),
  910. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  911. false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  912. RunThreads();
  913. EXPECT_EQ(7u, items.size());
  914. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  915. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  916. EXPECT_EQ(ComponentState::kUpdateError, items[1].state);
  917. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str());
  918. EXPECT_EQ(ComponentState::kCanUpdate, items[2].state);
  919. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str());
  920. EXPECT_EQ(ComponentState::kDownloading, items[3].state);
  921. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str());
  922. EXPECT_EQ(ComponentState::kDownloading, items[4].state);
  923. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str());
  924. EXPECT_EQ(ComponentState::kUpdating, items[5].state);
  925. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[5].id.c_str());
  926. EXPECT_EQ(ComponentState::kUpdated, items[6].state);
  927. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[6].id.c_str());
  928. update_client->RemoveObserver(&observer);
  929. }
  930. // Tests the update check for two CRXs scenario when no CrxComponent data is
  931. // provided for either component. In this case, no update check occurs, and
  932. // |COMPONENT_UPDATE_ERROR| event fires for both components.
  933. TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentDataAtAll) {
  934. class DataCallbackMock {
  935. public:
  936. static std::vector<absl::optional<CrxComponent>> Callback(
  937. const std::vector<std::string>& ids) {
  938. return {absl::nullopt, absl::nullopt};
  939. }
  940. };
  941. class CompletionCallbackMock {
  942. public:
  943. static void Callback(base::OnceClosure quit_closure, Error error) {
  944. EXPECT_EQ(Error::NONE, error);
  945. std::move(quit_closure).Run();
  946. }
  947. };
  948. class MockUpdateChecker : public UpdateChecker {
  949. public:
  950. static std::unique_ptr<UpdateChecker> Create(
  951. scoped_refptr<Configurator> config,
  952. PersistedData* metadata) {
  953. return std::make_unique<MockUpdateChecker>();
  954. }
  955. void CheckForUpdates(
  956. scoped_refptr<UpdateContext> context,
  957. const base::flat_map<std::string, std::string>& additional_attributes,
  958. UpdateCheckCallback update_check_callback) override {
  959. NOTREACHED();
  960. }
  961. };
  962. class MockCrxDownloader : public CrxDownloader {
  963. public:
  964. MockCrxDownloader() : CrxDownloader(nullptr) {}
  965. private:
  966. ~MockCrxDownloader() override = default;
  967. void DoStartDownload(const GURL& url) override { NOTREACHED(); }
  968. };
  969. class MockPingManager : public MockPingManagerImpl {
  970. public:
  971. explicit MockPingManager(scoped_refptr<Configurator> config)
  972. : MockPingManagerImpl(config) {}
  973. protected:
  974. ~MockPingManager() override {
  975. EXPECT_EQ(0u, MockPingManagerImpl::ping_data().size());
  976. }
  977. };
  978. SetMockCrxDownloader<MockCrxDownloader>();
  979. scoped_refptr<UpdateClient> update_client =
  980. base::MakeRefCounted<UpdateClientImpl>(
  981. config(), base::MakeRefCounted<MockPingManager>(config()),
  982. &MockUpdateChecker::Create);
  983. MockObserver observer;
  984. {
  985. InSequence seq;
  986. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  987. "jebgalgnebhfojomionfpkfelancnnkf"))
  988. .Times(1);
  989. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  990. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  991. .Times(1);
  992. }
  993. std::vector<CrxUpdateItem> items;
  994. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  995. EXPECT_CALL(*receiver, Receive(_))
  996. .WillRepeatedly(
  997. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  998. update_client->AddObserver(&observer);
  999. const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
  1000. "ihfokbkgjpifnbbojhneepfflplebdkc"};
  1001. update_client->Update(
  1002. ids, base::BindOnce(&DataCallbackMock::Callback),
  1003. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  1004. false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  1005. RunThreads();
  1006. EXPECT_EQ(2u, items.size());
  1007. EXPECT_EQ(ComponentState::kUpdateError, items[0].state);
  1008. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  1009. EXPECT_EQ(ComponentState::kUpdateError, items[1].state);
  1010. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str());
  1011. update_client->RemoveObserver(&observer);
  1012. }
  1013. // Tests the scenario where there is a download timeout for the first
  1014. // CRX. The update for the first CRX fails. The update client waits before
  1015. // attempting the update for the second CRX. This update succeeds.
  1016. TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
  1017. class DataCallbackMock {
  1018. public:
  1019. static std::vector<absl::optional<CrxComponent>> Callback(
  1020. const std::vector<std::string>& ids) {
  1021. CrxComponent crx1;
  1022. crx1.name = "test_jebg";
  1023. crx1.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  1024. crx1.version = base::Version("0.9");
  1025. crx1.installer = base::MakeRefCounted<TestInstaller>();
  1026. crx1.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  1027. CrxComponent crx2;
  1028. crx2.name = "test_ihfo";
  1029. crx2.pk_hash.assign(ihfo_hash, ihfo_hash + std::size(ihfo_hash));
  1030. crx2.version = base::Version("0.8");
  1031. crx2.installer = base::MakeRefCounted<TestInstaller>();
  1032. crx2.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  1033. return {crx1, crx2};
  1034. }
  1035. };
  1036. class CompletionCallbackMock {
  1037. public:
  1038. static void Callback(base::OnceClosure quit_closure, Error error) {
  1039. EXPECT_EQ(Error::NONE, error);
  1040. std::move(quit_closure).Run();
  1041. }
  1042. };
  1043. class MockUpdateChecker : public UpdateChecker {
  1044. public:
  1045. static std::unique_ptr<UpdateChecker> Create(
  1046. scoped_refptr<Configurator> config,
  1047. PersistedData* metadata) {
  1048. return std::make_unique<MockUpdateChecker>();
  1049. }
  1050. void CheckForUpdates(
  1051. scoped_refptr<UpdateContext> context,
  1052. const base::flat_map<std::string, std::string>& additional_attributes,
  1053. UpdateCheckCallback update_check_callback) override {
  1054. /*
  1055. Mock the following response:
  1056. <?xml version='1.0' encoding='UTF-8'?>
  1057. <response protocol='3.1'>
  1058. <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
  1059. <updatecheck status='ok'>
  1060. <urls>
  1061. <url codebase='http://localhost/download/'/>
  1062. </urls>
  1063. <manifest version='1.0' prodversionmin='11.0.1.0'>
  1064. <packages>
  1065. <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
  1066. hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
  1067. a284a7cd8059c3409ce0498'/>
  1068. </packages>
  1069. </manifest>
  1070. </updatecheck>
  1071. </app>
  1072. <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
  1073. <updatecheck status='ok'>
  1074. <urls>
  1075. <url codebase='http://localhost/download/'/>
  1076. </urls>
  1077. <manifest version='1.0' prodversionmin='11.0.1.0'>
  1078. <packages>
  1079. <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'
  1080. hash_sha256='8f5aa190311237cae00675af87ff457f278cd1a05
  1081. 895470ac5d46647d4a3c2ea'/>
  1082. </packages>
  1083. </manifest>
  1084. </updatecheck>
  1085. </app>
  1086. </response>
  1087. */
  1088. EXPECT_FALSE(context->session_id.empty());
  1089. EXPECT_EQ(2u, context->components_to_check_for_updates.size());
  1090. ProtocolParser::Results results;
  1091. {
  1092. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  1093. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  1094. EXPECT_EQ(1u, context->components.count(id));
  1095. ProtocolParser::Result::Manifest::Package package;
  1096. package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
  1097. package.hash_sha256 =
  1098. "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
  1099. ProtocolParser::Result result;
  1100. result.extension_id = id;
  1101. result.status = "ok";
  1102. result.crx_urls.push_back(GURL("http://localhost/download/"));
  1103. result.manifest.version = "1.0";
  1104. result.manifest.browser_min_version = "11.0.1.0";
  1105. result.manifest.packages.push_back(package);
  1106. results.list.push_back(result);
  1107. }
  1108. {
  1109. const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
  1110. EXPECT_EQ(id, context->components_to_check_for_updates[1]);
  1111. EXPECT_EQ(1u, context->components.count(id));
  1112. ProtocolParser::Result::Manifest::Package package;
  1113. package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
  1114. package.hash_sha256 =
  1115. "8f5aa190311237cae00675af87ff457f278cd1a05895470ac5d46647d4a3c2ea";
  1116. ProtocolParser::Result result;
  1117. result.extension_id = id;
  1118. result.status = "ok";
  1119. result.crx_urls.push_back(GURL("http://localhost/download/"));
  1120. result.manifest.version = "1.0";
  1121. result.manifest.browser_min_version = "11.0.1.0";
  1122. result.manifest.packages.push_back(package);
  1123. results.list.push_back(result);
  1124. }
  1125. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1126. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  1127. ErrorCategory::kNone, 0, 0));
  1128. }
  1129. };
  1130. class MockCrxDownloader : public CrxDownloader {
  1131. public:
  1132. MockCrxDownloader() : CrxDownloader(nullptr) {}
  1133. private:
  1134. ~MockCrxDownloader() override = default;
  1135. void DoStartDownload(const GURL& url) override {
  1136. DownloadMetrics download_metrics;
  1137. FilePath path;
  1138. Result result;
  1139. if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") {
  1140. download_metrics.url = url;
  1141. download_metrics.downloader = DownloadMetrics::kNone;
  1142. download_metrics.error = -118;
  1143. download_metrics.downloaded_bytes = 0;
  1144. download_metrics.total_bytes = 0;
  1145. download_metrics.download_time_ms = 1000;
  1146. // The result must not include a file path in the case of errors.
  1147. result.error = -118;
  1148. } else if (url.path() ==
  1149. "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
  1150. download_metrics.url = url;
  1151. download_metrics.downloader = DownloadMetrics::kNone;
  1152. download_metrics.error = 0;
  1153. download_metrics.downloaded_bytes = 53638;
  1154. download_metrics.total_bytes = 53638;
  1155. download_metrics.download_time_ms = 2000;
  1156. EXPECT_TRUE(MakeTestFile(
  1157. TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
  1158. result.error = 0;
  1159. result.response = path;
  1160. } else {
  1161. NOTREACHED();
  1162. }
  1163. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1164. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  1165. base::Unretained(this),
  1166. download_metrics.downloaded_bytes,
  1167. download_metrics.total_bytes));
  1168. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1169. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  1170. base::Unretained(this), true, result,
  1171. download_metrics));
  1172. }
  1173. };
  1174. class MockPingManager : public MockPingManagerImpl {
  1175. public:
  1176. explicit MockPingManager(scoped_refptr<Configurator> config)
  1177. : MockPingManagerImpl(config) {}
  1178. protected:
  1179. ~MockPingManager() override {
  1180. const auto ping_data = MockPingManagerImpl::ping_data();
  1181. EXPECT_EQ(2u, ping_data.size());
  1182. EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
  1183. EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
  1184. EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
  1185. EXPECT_EQ(1, static_cast<int>(ping_data[0].error_category));
  1186. EXPECT_EQ(-118, ping_data[0].error_code);
  1187. EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[1].id);
  1188. EXPECT_EQ(base::Version("0.8"), ping_data[1].previous_version);
  1189. EXPECT_EQ(base::Version("1.0"), ping_data[1].next_version);
  1190. EXPECT_EQ(0, static_cast<int>(ping_data[1].error_category));
  1191. EXPECT_EQ(0, ping_data[1].error_code);
  1192. }
  1193. };
  1194. SetMockCrxDownloader<MockCrxDownloader>();
  1195. scoped_refptr<UpdateClient> update_client =
  1196. base::MakeRefCounted<UpdateClientImpl>(
  1197. config(), base::MakeRefCounted<MockPingManager>(config()),
  1198. &MockUpdateChecker::Create);
  1199. MockObserver observer;
  1200. {
  1201. InSequence seq;
  1202. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  1203. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  1204. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  1205. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  1206. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  1207. "jebgalgnebhfojomionfpkfelancnnkf"))
  1208. .Times(AtLeast(1));
  1209. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  1210. "jebgalgnebhfojomionfpkfelancnnkf"))
  1211. .Times(1)
  1212. .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
  1213. CrxUpdateItem item;
  1214. EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
  1215. EXPECT_EQ(ComponentState::kUpdateError, item.state);
  1216. EXPECT_EQ(1, static_cast<int>(item.error_category));
  1217. EXPECT_EQ(-118, item.error_code);
  1218. EXPECT_EQ(0, item.extra_code1);
  1219. }));
  1220. }
  1221. {
  1222. InSequence seq;
  1223. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  1224. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  1225. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  1226. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  1227. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_WAIT,
  1228. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  1229. .Times(AnyNumber());
  1230. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  1231. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  1232. .Times(AtLeast(1));
  1233. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
  1234. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  1235. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
  1236. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  1237. }
  1238. std::vector<CrxUpdateItem> items;
  1239. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  1240. EXPECT_CALL(*receiver, Receive(_))
  1241. .WillRepeatedly(
  1242. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  1243. update_client->AddObserver(&observer);
  1244. const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
  1245. "ihfokbkgjpifnbbojhneepfflplebdkc"};
  1246. update_client->Update(
  1247. ids, base::BindOnce(&DataCallbackMock::Callback),
  1248. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  1249. false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  1250. RunThreads();
  1251. EXPECT_EQ(11u, items.size());
  1252. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  1253. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  1254. EXPECT_EQ(ComponentState::kChecking, items[1].state);
  1255. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str());
  1256. EXPECT_EQ(ComponentState::kCanUpdate, items[2].state);
  1257. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str());
  1258. EXPECT_EQ(ComponentState::kDownloading, items[3].state);
  1259. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str());
  1260. EXPECT_EQ(ComponentState::kDownloading, items[4].state);
  1261. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str());
  1262. EXPECT_EQ(ComponentState::kUpdateError, items[5].state);
  1263. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[5].id.c_str());
  1264. EXPECT_EQ(ComponentState::kCanUpdate, items[6].state);
  1265. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[6].id.c_str());
  1266. EXPECT_EQ(ComponentState::kDownloading, items[7].state);
  1267. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[7].id.c_str());
  1268. EXPECT_EQ(ComponentState::kDownloading, items[8].state);
  1269. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[8].id.c_str());
  1270. EXPECT_EQ(ComponentState::kUpdating, items[9].state);
  1271. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[9].id.c_str());
  1272. EXPECT_EQ(ComponentState::kUpdated, items[10].state);
  1273. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[10].id.c_str());
  1274. update_client->RemoveObserver(&observer);
  1275. }
  1276. // Tests the differential update scenario for one CRX. Tests install progress
  1277. // for differential and full updates.
  1278. TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
  1279. class DataCallbackMock {
  1280. public:
  1281. static std::vector<absl::optional<CrxComponent>> Callback(
  1282. const std::vector<std::string>& ids) {
  1283. static int num_calls = 0;
  1284. // Must use the same stateful installer object.
  1285. static auto installer = base::MakeRefCounted<VersionedTestInstaller>();
  1286. installer->set_installer_progress_samples({-1, 50, 100});
  1287. ++num_calls;
  1288. CrxComponent crx;
  1289. crx.name = "test_ihfo";
  1290. crx.pk_hash.assign(ihfo_hash, ihfo_hash + std::size(ihfo_hash));
  1291. crx.installer = installer;
  1292. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  1293. if (num_calls == 1) {
  1294. crx.version = base::Version("0.8");
  1295. } else if (num_calls == 2) {
  1296. crx.version = base::Version("1.0");
  1297. } else {
  1298. NOTREACHED();
  1299. }
  1300. return {crx};
  1301. }
  1302. };
  1303. class CompletionCallbackMock {
  1304. public:
  1305. static void Callback(base::OnceClosure quit_closure, Error error) {
  1306. EXPECT_EQ(Error::NONE, error);
  1307. std::move(quit_closure).Run();
  1308. }
  1309. };
  1310. class MockUpdateChecker : public UpdateChecker {
  1311. public:
  1312. static std::unique_ptr<UpdateChecker> Create(
  1313. scoped_refptr<Configurator> config,
  1314. PersistedData* metadata) {
  1315. return std::make_unique<MockUpdateChecker>();
  1316. }
  1317. void CheckForUpdates(
  1318. scoped_refptr<UpdateContext> context,
  1319. const base::flat_map<std::string, std::string>& additional_attributes,
  1320. UpdateCheckCallback update_check_callback) override {
  1321. EXPECT_FALSE(context->session_id.empty());
  1322. static int num_call = 0;
  1323. ++num_call;
  1324. ProtocolParser::Results results;
  1325. if (num_call == 1) {
  1326. /*
  1327. Mock the following response:
  1328. <?xml version='1.0' encoding='UTF-8'?>
  1329. <response protocol='3.1'>
  1330. <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
  1331. <updatecheck status='ok'>
  1332. <urls>
  1333. <url codebase='http://localhost/download/'/>
  1334. </urls>
  1335. <manifest version='1.0' prodversionmin='11.0.1.0'>
  1336. <packages>
  1337. <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'
  1338. hash_sha256='813c59747e139a608b3b5fc49633affc6db57437
  1339. 3f309f156ea6d27229c0b3f9'/>
  1340. </packages>
  1341. </manifest>
  1342. </updatecheck>
  1343. </app>
  1344. </response>
  1345. */
  1346. const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
  1347. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  1348. EXPECT_EQ(1u, context->components.count(id));
  1349. ProtocolParser::Result::Manifest::Package package;
  1350. package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
  1351. package.hash_sha256 =
  1352. "8f5aa190311237cae00675af87ff457f278cd1a05895470ac5d46647d4a3c2ea";
  1353. ProtocolParser::Result result;
  1354. result.extension_id = id;
  1355. result.status = "ok";
  1356. result.crx_urls.push_back(GURL("http://localhost/download/"));
  1357. result.manifest.version = "1.0";
  1358. result.manifest.browser_min_version = "11.0.1.0";
  1359. result.manifest.packages.push_back(package);
  1360. results.list.push_back(result);
  1361. } else if (num_call == 2) {
  1362. /*
  1363. Mock the following response:
  1364. <?xml version='1.0' encoding='UTF-8'?>
  1365. <response protocol='3.1'>
  1366. <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
  1367. <updatecheck status='ok'>
  1368. <urls>
  1369. <url codebase='http://localhost/download/'/>
  1370. <url codebasediff='http://localhost/download/'/>
  1371. </urls>
  1372. <manifest version='2.0' prodversionmin='11.0.1.0'>
  1373. <packages>
  1374. <package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx'
  1375. namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx'
  1376. hash_sha256='c87d8742c3ff3d7a0cb6f3c91aa2fcf3dea6361
  1377. 8086a7db1c5be5300e1d4d6b6'
  1378. fp='22'
  1379. hashdiff_sha256='0fd48a5dd87006a709756cfc47198cbc4c4
  1380. 928f33ac4277d79573c15164a33eb'/>
  1381. </packages>
  1382. </manifest>
  1383. </updatecheck>
  1384. </app>
  1385. </response>
  1386. */
  1387. const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
  1388. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  1389. EXPECT_EQ(1u, context->components.count(id));
  1390. ProtocolParser::Result::Manifest::Package package;
  1391. package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx";
  1392. package.namediff = "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx";
  1393. package.hash_sha256 =
  1394. "c87d8742c3ff3d7a0cb6f3c91aa2fcf3dea63618086a7db1c5be5300e1d4d6b6";
  1395. package.hashdiff_sha256 =
  1396. "0fd48a5dd87006a709756cfc47198cbc4c4928f33ac4277d79573c15164a33eb";
  1397. package.fingerprint = "22";
  1398. ProtocolParser::Result result;
  1399. result.extension_id = id;
  1400. result.status = "ok";
  1401. result.crx_urls.push_back(GURL("http://localhost/download/"));
  1402. result.crx_diffurls.push_back(GURL("http://localhost/download/"));
  1403. result.manifest.version = "2.0";
  1404. result.manifest.browser_min_version = "11.0.1.0";
  1405. result.manifest.packages.push_back(package);
  1406. results.list.push_back(result);
  1407. } else {
  1408. NOTREACHED();
  1409. }
  1410. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1411. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  1412. ErrorCategory::kNone, 0, 0));
  1413. }
  1414. };
  1415. class MockCrxDownloader : public CrxDownloader {
  1416. public:
  1417. MockCrxDownloader() : CrxDownloader(nullptr) {}
  1418. private:
  1419. ~MockCrxDownloader() override = default;
  1420. void DoStartDownload(const GURL& url) override {
  1421. DownloadMetrics download_metrics;
  1422. FilePath path;
  1423. Result result;
  1424. if (url.path() == "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
  1425. download_metrics.url = url;
  1426. download_metrics.downloader = DownloadMetrics::kNone;
  1427. download_metrics.error = 0;
  1428. download_metrics.downloaded_bytes = 53638;
  1429. download_metrics.total_bytes = 53638;
  1430. download_metrics.download_time_ms = 2000;
  1431. EXPECT_TRUE(MakeTestFile(
  1432. TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
  1433. result.error = 0;
  1434. result.response = path;
  1435. } else if (url.path() ==
  1436. "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx") {
  1437. download_metrics.url = url;
  1438. download_metrics.downloader = DownloadMetrics::kNone;
  1439. download_metrics.error = 0;
  1440. download_metrics.downloaded_bytes = 2105;
  1441. download_metrics.total_bytes = 2105;
  1442. download_metrics.download_time_ms = 1000;
  1443. EXPECT_TRUE(MakeTestFile(
  1444. TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), &path));
  1445. result.error = 0;
  1446. result.response = path;
  1447. } else {
  1448. NOTREACHED();
  1449. }
  1450. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1451. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  1452. base::Unretained(this),
  1453. download_metrics.downloaded_bytes / 2,
  1454. download_metrics.total_bytes));
  1455. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1456. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  1457. base::Unretained(this),
  1458. download_metrics.downloaded_bytes,
  1459. download_metrics.total_bytes));
  1460. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1461. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  1462. base::Unretained(this), true, result,
  1463. download_metrics));
  1464. }
  1465. };
  1466. class MockPingManager : public MockPingManagerImpl {
  1467. public:
  1468. explicit MockPingManager(scoped_refptr<Configurator> config)
  1469. : MockPingManagerImpl(config) {}
  1470. protected:
  1471. ~MockPingManager() override {
  1472. const auto ping_data = MockPingManagerImpl::ping_data();
  1473. EXPECT_EQ(2u, ping_data.size());
  1474. EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[0].id);
  1475. EXPECT_EQ(base::Version("0.8"), ping_data[0].previous_version);
  1476. EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
  1477. EXPECT_EQ(0, static_cast<int>(ping_data[0].error_category));
  1478. EXPECT_EQ(0, ping_data[0].error_code);
  1479. EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[1].id);
  1480. EXPECT_EQ(base::Version("1.0"), ping_data[1].previous_version);
  1481. EXPECT_EQ(base::Version("2.0"), ping_data[1].next_version);
  1482. EXPECT_FALSE(ping_data[1].diff_update_failed);
  1483. EXPECT_EQ(0, static_cast<int>(ping_data[1].diff_error_category));
  1484. EXPECT_EQ(0, ping_data[1].diff_error_code);
  1485. EXPECT_EQ(0, static_cast<int>(ping_data[1].error_category));
  1486. EXPECT_EQ(0, ping_data[1].error_code);
  1487. }
  1488. };
  1489. SetMockCrxDownloader<MockCrxDownloader>();
  1490. scoped_refptr<UpdateClient> update_client =
  1491. base::MakeRefCounted<UpdateClientImpl>(
  1492. config(), base::MakeRefCounted<MockPingManager>(config()),
  1493. &MockUpdateChecker::Create);
  1494. MockObserver observer;
  1495. {
  1496. InSequence seq;
  1497. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  1498. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  1499. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  1500. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  1501. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  1502. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  1503. .Times(AtLeast(1));
  1504. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
  1505. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  1506. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_UPDATING,
  1507. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  1508. .Times(3);
  1509. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
  1510. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  1511. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  1512. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  1513. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  1514. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  1515. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  1516. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  1517. .Times(AtLeast(1));
  1518. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
  1519. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  1520. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_UPDATING,
  1521. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  1522. .Times(3);
  1523. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
  1524. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  1525. }
  1526. update_client->AddObserver(&observer);
  1527. const std::vector<std::string> ids = {"ihfokbkgjpifnbbojhneepfflplebdkc"};
  1528. {
  1529. std::vector<CrxUpdateItem> items;
  1530. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  1531. EXPECT_CALL(*receiver, Receive(_))
  1532. .WillRepeatedly(
  1533. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  1534. base::RunLoop runloop;
  1535. update_client->Update(
  1536. ids, base::BindOnce(&DataCallbackMock::Callback),
  1537. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  1538. false,
  1539. base::BindOnce(&CompletionCallbackMock::Callback,
  1540. runloop.QuitClosure()));
  1541. runloop.Run();
  1542. EXPECT_EQ(10u, items.size());
  1543. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  1544. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[0].id.c_str());
  1545. EXPECT_EQ(ComponentState::kCanUpdate, items[1].state);
  1546. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str());
  1547. EXPECT_EQ(ComponentState::kDownloading, items[2].state);
  1548. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[2].id.c_str());
  1549. EXPECT_EQ(ComponentState::kDownloading, items[3].state);
  1550. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[3].id.c_str());
  1551. EXPECT_EQ(ComponentState::kDownloading, items[4].state);
  1552. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[4].id.c_str());
  1553. EXPECT_EQ(ComponentState::kUpdating, items[5].state);
  1554. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[5].id.c_str());
  1555. EXPECT_EQ(ComponentState::kUpdating, items[6].state);
  1556. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[6].id.c_str());
  1557. EXPECT_EQ(ComponentState::kUpdating, items[7].state);
  1558. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[7].id.c_str());
  1559. EXPECT_EQ(ComponentState::kUpdating, items[8].state);
  1560. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[8].id.c_str());
  1561. EXPECT_EQ(ComponentState::kUpdated, items[9].state);
  1562. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[9].id.c_str());
  1563. std::vector<int> samples = {-1, -1, -1, -1, -1, -1, -1, 50, 100, 100};
  1564. EXPECT_EQ(items.size(), samples.size());
  1565. for (size_t i = 0; i != items.size(); ++i)
  1566. EXPECT_EQ(items[i].install_progress, samples[i]);
  1567. }
  1568. {
  1569. std::vector<CrxUpdateItem> items;
  1570. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  1571. EXPECT_CALL(*receiver, Receive(_))
  1572. .WillRepeatedly(
  1573. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  1574. base::RunLoop runloop;
  1575. update_client->Update(
  1576. ids, base::BindOnce(&DataCallbackMock::Callback),
  1577. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  1578. false,
  1579. base::BindOnce(&CompletionCallbackMock::Callback,
  1580. runloop.QuitClosure()));
  1581. runloop.Run();
  1582. EXPECT_EQ(10u, items.size());
  1583. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  1584. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[0].id.c_str());
  1585. EXPECT_EQ(ComponentState::kCanUpdate, items[1].state);
  1586. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str());
  1587. EXPECT_EQ(ComponentState::kDownloadingDiff, items[2].state);
  1588. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[2].id.c_str());
  1589. EXPECT_EQ(ComponentState::kDownloadingDiff, items[3].state);
  1590. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[3].id.c_str());
  1591. EXPECT_EQ(ComponentState::kDownloadingDiff, items[4].state);
  1592. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[4].id.c_str());
  1593. EXPECT_EQ(ComponentState::kUpdatingDiff, items[5].state);
  1594. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[5].id.c_str());
  1595. EXPECT_EQ(ComponentState::kUpdatingDiff, items[6].state);
  1596. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[6].id.c_str());
  1597. EXPECT_EQ(ComponentState::kUpdatingDiff, items[7].state);
  1598. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[7].id.c_str());
  1599. EXPECT_EQ(ComponentState::kUpdatingDiff, items[8].state);
  1600. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[8].id.c_str());
  1601. EXPECT_EQ(ComponentState::kUpdated, items[9].state);
  1602. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[9].id.c_str());
  1603. std::vector<int> samples = {-1, -1, -1, -1, -1, -1, -1, 50, 100, 100};
  1604. EXPECT_EQ(items.size(), samples.size());
  1605. for (size_t i = 0; i != items.size(); ++i)
  1606. EXPECT_EQ(items[i].install_progress, samples[i]);
  1607. }
  1608. update_client->RemoveObserver(&observer);
  1609. }
  1610. // Tests the update scenario for one CRX where the CRX installer returns
  1611. // an error. Tests that the |unpack_path| argument refers to a valid path
  1612. // then |Install| is called, then tests that the |unpack| path is deleted
  1613. // by the |update_client| code before the test ends.
  1614. TEST_F(UpdateClientTest, OneCrxInstallError) {
  1615. class MockInstaller : public CrxInstaller {
  1616. public:
  1617. MOCK_METHOD1(OnUpdateError, void(int error));
  1618. MOCK_METHOD1(DoInstall, void(const base::FilePath& unpack_path));
  1619. MOCK_METHOD2(GetInstalledFile,
  1620. bool(const std::string& file, base::FilePath* installed_file));
  1621. MOCK_METHOD0(Uninstall, bool());
  1622. void Install(const base::FilePath& unpack_path,
  1623. const std::string& public_key,
  1624. std::unique_ptr<InstallParams> /*install_params*/,
  1625. ProgressCallback progress_callback,
  1626. Callback callback) override {
  1627. DoInstall(unpack_path);
  1628. unpack_path_ = unpack_path;
  1629. EXPECT_TRUE(base::DirectoryExists(unpack_path_));
  1630. base::ThreadPool::PostTask(
  1631. FROM_HERE, {base::MayBlock()},
  1632. base::BindOnce(std::move(callback),
  1633. CrxInstaller::Result(InstallError::GENERIC_ERROR)));
  1634. }
  1635. protected:
  1636. ~MockInstaller() override {
  1637. // The unpack path is deleted unconditionally by the component state code,
  1638. // which is driving this installer. Therefore, the unpack path must not
  1639. // exist when this object is destroyed.
  1640. if (!unpack_path_.empty())
  1641. EXPECT_FALSE(base::DirectoryExists(unpack_path_));
  1642. }
  1643. private:
  1644. // Contains the |unpack_path| argument of the Install call.
  1645. base::FilePath unpack_path_;
  1646. };
  1647. class DataCallbackMock {
  1648. public:
  1649. static std::vector<absl::optional<CrxComponent>> Callback(
  1650. const std::vector<std::string>& ids) {
  1651. scoped_refptr<MockInstaller> installer =
  1652. base::MakeRefCounted<MockInstaller>();
  1653. EXPECT_CALL(*installer, OnUpdateError(_)).Times(0);
  1654. EXPECT_CALL(*installer, DoInstall(_)).Times(1);
  1655. EXPECT_CALL(*installer, GetInstalledFile(_, _)).Times(0);
  1656. EXPECT_CALL(*installer, Uninstall()).Times(0);
  1657. CrxComponent crx;
  1658. crx.name = "test_jebg";
  1659. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  1660. crx.version = base::Version("0.9");
  1661. crx.installer = installer;
  1662. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  1663. return {crx};
  1664. }
  1665. };
  1666. class CompletionCallbackMock {
  1667. public:
  1668. static void Callback(base::OnceClosure quit_closure, Error error) {
  1669. EXPECT_EQ(Error::NONE, error);
  1670. std::move(quit_closure).Run();
  1671. }
  1672. };
  1673. class MockUpdateChecker : public UpdateChecker {
  1674. public:
  1675. static std::unique_ptr<UpdateChecker> Create(
  1676. scoped_refptr<Configurator> config,
  1677. PersistedData* metadata) {
  1678. return std::make_unique<MockUpdateChecker>();
  1679. }
  1680. void CheckForUpdates(
  1681. scoped_refptr<UpdateContext> context,
  1682. const base::flat_map<std::string, std::string>& additional_attributes,
  1683. UpdateCheckCallback update_check_callback) override {
  1684. /*
  1685. Mock the following response:
  1686. <?xml version='1.0' encoding='UTF-8'?>
  1687. <response protocol='3.1'>
  1688. <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
  1689. <updatecheck status='ok'>
  1690. <urls>
  1691. <url codebase='http://localhost/download/'/>
  1692. </urls>
  1693. <manifest version='1.0' prodversionmin='11.0.1.0'>
  1694. <packages>
  1695. <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
  1696. hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
  1697. a284a7cd8059c3409ce0498'/>
  1698. </packages>
  1699. </manifest>
  1700. </updatecheck>
  1701. </app>
  1702. </response>
  1703. */
  1704. EXPECT_FALSE(context->session_id.empty());
  1705. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  1706. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  1707. EXPECT_EQ(1u, context->components.count(id));
  1708. ProtocolParser::Result::Manifest::Package package;
  1709. package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
  1710. package.hash_sha256 =
  1711. "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
  1712. ProtocolParser::Result result;
  1713. result.extension_id = id;
  1714. result.status = "ok";
  1715. result.crx_urls.push_back(GURL("http://localhost/download/"));
  1716. result.manifest.version = "1.0";
  1717. result.manifest.browser_min_version = "11.0.1.0";
  1718. result.manifest.packages.push_back(package);
  1719. ProtocolParser::Results results;
  1720. results.list.push_back(result);
  1721. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1722. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  1723. ErrorCategory::kNone, 0, 0));
  1724. }
  1725. };
  1726. class MockCrxDownloader : public CrxDownloader {
  1727. public:
  1728. MockCrxDownloader() : CrxDownloader(nullptr) {}
  1729. private:
  1730. ~MockCrxDownloader() override = default;
  1731. void DoStartDownload(const GURL& url) override {
  1732. DownloadMetrics download_metrics;
  1733. download_metrics.url = url;
  1734. download_metrics.downloader = DownloadMetrics::kNone;
  1735. download_metrics.error = 0;
  1736. download_metrics.downloaded_bytes = 1843;
  1737. download_metrics.total_bytes = 1843;
  1738. download_metrics.download_time_ms = 1000;
  1739. FilePath path;
  1740. EXPECT_TRUE(MakeTestFile(
  1741. TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
  1742. Result result;
  1743. result.error = 0;
  1744. result.response = path;
  1745. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1746. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  1747. base::Unretained(this),
  1748. download_metrics.downloaded_bytes,
  1749. download_metrics.total_bytes));
  1750. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1751. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  1752. base::Unretained(this), true, result,
  1753. download_metrics));
  1754. }
  1755. };
  1756. class MockPingManager : public MockPingManagerImpl {
  1757. public:
  1758. explicit MockPingManager(scoped_refptr<Configurator> config)
  1759. : MockPingManagerImpl(config) {}
  1760. protected:
  1761. ~MockPingManager() override {
  1762. const auto ping_data = MockPingManagerImpl::ping_data();
  1763. EXPECT_EQ(1u, ping_data.size());
  1764. EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
  1765. EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
  1766. EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
  1767. EXPECT_EQ(3, static_cast<int>(ping_data[0].error_category)); // kInstall.
  1768. EXPECT_EQ(9, ping_data[0].error_code); // kInstallerError.
  1769. }
  1770. };
  1771. SetMockCrxDownloader<MockCrxDownloader>();
  1772. scoped_refptr<UpdateClient> update_client =
  1773. base::MakeRefCounted<UpdateClientImpl>(
  1774. config(), base::MakeRefCounted<MockPingManager>(config()),
  1775. &MockUpdateChecker::Create);
  1776. MockObserver observer;
  1777. {
  1778. InSequence seq;
  1779. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  1780. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  1781. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  1782. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  1783. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  1784. "jebgalgnebhfojomionfpkfelancnnkf"))
  1785. .Times(AtLeast(1));
  1786. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
  1787. "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
  1788. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  1789. "jebgalgnebhfojomionfpkfelancnnkf"))
  1790. .Times(1);
  1791. }
  1792. std::vector<CrxUpdateItem> items;
  1793. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  1794. EXPECT_CALL(*receiver, Receive(_))
  1795. .WillRepeatedly(
  1796. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  1797. update_client->AddObserver(&observer);
  1798. std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"};
  1799. update_client->Update(
  1800. ids, base::BindOnce(&DataCallbackMock::Callback),
  1801. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  1802. false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  1803. RunThreads();
  1804. EXPECT_EQ(6u, items.size());
  1805. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  1806. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  1807. EXPECT_EQ(ComponentState::kCanUpdate, items[1].state);
  1808. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[1].id.c_str());
  1809. EXPECT_EQ(ComponentState::kDownloading, items[2].state);
  1810. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str());
  1811. EXPECT_EQ(ComponentState::kDownloading, items[3].state);
  1812. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str());
  1813. EXPECT_EQ(ComponentState::kUpdating, items[4].state);
  1814. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str());
  1815. EXPECT_EQ(ComponentState::kUpdateError, items[5].state);
  1816. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[5].id.c_str());
  1817. update_client->RemoveObserver(&observer);
  1818. }
  1819. // Tests the fallback from differential to full update scenario for one CRX.
  1820. TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
  1821. class DataCallbackMock {
  1822. public:
  1823. static std::vector<absl::optional<CrxComponent>> Callback(
  1824. const std::vector<std::string>& ids) {
  1825. static int num_calls = 0;
  1826. // Must use the same stateful installer object.
  1827. static auto installer = base::MakeRefCounted<VersionedTestInstaller>();
  1828. ++num_calls;
  1829. CrxComponent crx;
  1830. crx.name = "test_ihfo";
  1831. crx.pk_hash.assign(ihfo_hash, ihfo_hash + std::size(ihfo_hash));
  1832. crx.installer = installer;
  1833. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  1834. if (num_calls == 1) {
  1835. crx.version = base::Version("0.8");
  1836. } else if (num_calls == 2) {
  1837. crx.version = base::Version("1.0");
  1838. } else {
  1839. NOTREACHED();
  1840. }
  1841. return {crx};
  1842. }
  1843. };
  1844. class CompletionCallbackMock {
  1845. public:
  1846. static void Callback(base::OnceClosure quit_closure, Error error) {
  1847. EXPECT_EQ(Error::NONE, error);
  1848. std::move(quit_closure).Run();
  1849. }
  1850. };
  1851. class MockUpdateChecker : public UpdateChecker {
  1852. public:
  1853. static std::unique_ptr<UpdateChecker> Create(
  1854. scoped_refptr<Configurator> config,
  1855. PersistedData* metadata) {
  1856. return std::make_unique<MockUpdateChecker>();
  1857. }
  1858. void CheckForUpdates(
  1859. scoped_refptr<UpdateContext> context,
  1860. const base::flat_map<std::string, std::string>& additional_attributes,
  1861. UpdateCheckCallback update_check_callback) override {
  1862. EXPECT_FALSE(context->session_id.empty());
  1863. static int num_call = 0;
  1864. ++num_call;
  1865. ProtocolParser::Results results;
  1866. if (num_call == 1) {
  1867. /*
  1868. Mock the following response:
  1869. <?xml version='1.0' encoding='UTF-8'?>
  1870. <response protocol='3.1'>
  1871. <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
  1872. <updatecheck status='ok'>
  1873. <urls>
  1874. <url codebase='http://localhost/download/'/>
  1875. </urls>
  1876. <manifest version='1.0' prodversionmin='11.0.1.0'>
  1877. <packages>
  1878. <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'
  1879. hash_sha256='813c59747e139a608b3b5fc49633affc6db57437
  1880. 3f309f156ea6d27229c0b3f9'
  1881. fp='1'/>
  1882. </packages>
  1883. </manifest>
  1884. </updatecheck>
  1885. </app>
  1886. </response>
  1887. */
  1888. const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
  1889. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  1890. EXPECT_EQ(1u, context->components.count(id));
  1891. ProtocolParser::Result::Manifest::Package package;
  1892. package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
  1893. package.hash_sha256 =
  1894. "8f5aa190311237cae00675af87ff457f278cd1a05895470ac5d46647d4a3c2ea";
  1895. package.fingerprint = "1";
  1896. ProtocolParser::Result result;
  1897. result.extension_id = id;
  1898. result.status = "ok";
  1899. result.crx_urls.push_back(GURL("http://localhost/download/"));
  1900. result.manifest.version = "1.0";
  1901. result.manifest.browser_min_version = "11.0.1.0";
  1902. result.manifest.packages.push_back(package);
  1903. results.list.push_back(result);
  1904. } else if (num_call == 2) {
  1905. /*
  1906. Mock the following response:
  1907. <?xml version='1.0' encoding='UTF-8'?>
  1908. <response protocol='3.1'>
  1909. <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
  1910. <updatecheck status='ok'>
  1911. <urls>
  1912. <url codebase='http://localhost/download/'/>
  1913. <url codebasediff='http://localhost/download/'/>
  1914. </urls>
  1915. <manifest version='2.0' prodversionmin='11.0.1.0'>
  1916. <packages>
  1917. <package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx'
  1918. namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx'
  1919. hash_sha256='c87d8742c3ff3d7a0cb6f3c91aa2fcf3dea6361
  1920. 8086a7db1c5be5300e1d4d6b6'
  1921. fp='22'
  1922. hashdiff_sha256='0fd48a5dd87006a709756cfc47198cbc4c4
  1923. 928f33ac4277d79573c15164a33eb'/>
  1924. </packages>
  1925. </manifest>
  1926. </updatecheck>
  1927. </app>
  1928. </response>
  1929. */
  1930. const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
  1931. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  1932. EXPECT_EQ(1u, context->components.count(id));
  1933. ProtocolParser::Result::Manifest::Package package;
  1934. package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx";
  1935. package.namediff = "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx";
  1936. package.hash_sha256 =
  1937. "c87d8742c3ff3d7a0cb6f3c91aa2fcf3dea63618086a7db1c5be5300e1d4d6b6";
  1938. package.hashdiff_sha256 =
  1939. "0fd48a5dd87006a709756cfc47198cbc4c4928f33ac4277d79573c15164a33eb";
  1940. package.fingerprint = "22";
  1941. ProtocolParser::Result result;
  1942. result.extension_id = id;
  1943. result.status = "ok";
  1944. result.crx_urls.push_back(GURL("http://localhost/download/"));
  1945. result.crx_diffurls.push_back(GURL("http://localhost/download/"));
  1946. result.manifest.version = "2.0";
  1947. result.manifest.browser_min_version = "11.0.1.0";
  1948. result.manifest.packages.push_back(package);
  1949. results.list.push_back(result);
  1950. } else {
  1951. NOTREACHED();
  1952. }
  1953. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1954. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  1955. ErrorCategory::kNone, 0, 0));
  1956. }
  1957. };
  1958. class MockCrxDownloader : public CrxDownloader {
  1959. public:
  1960. MockCrxDownloader() : CrxDownloader(nullptr) {}
  1961. private:
  1962. ~MockCrxDownloader() override = default;
  1963. void DoStartDownload(const GURL& url) override {
  1964. DownloadMetrics download_metrics;
  1965. FilePath path;
  1966. Result result;
  1967. if (url.path() == "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
  1968. download_metrics.url = url;
  1969. download_metrics.downloader = DownloadMetrics::kNone;
  1970. download_metrics.error = 0;
  1971. download_metrics.downloaded_bytes = 53638;
  1972. download_metrics.total_bytes = 53638;
  1973. download_metrics.download_time_ms = 2000;
  1974. EXPECT_TRUE(MakeTestFile(
  1975. TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
  1976. result.error = 0;
  1977. result.response = path;
  1978. } else if (url.path() ==
  1979. "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx") {
  1980. // A download error is injected on this execution path.
  1981. download_metrics.url = url;
  1982. download_metrics.downloader = DownloadMetrics::kNone;
  1983. download_metrics.error = -1;
  1984. download_metrics.downloaded_bytes = 0;
  1985. download_metrics.total_bytes = 2105;
  1986. download_metrics.download_time_ms = 1000;
  1987. // The response must not include a file path in the case of errors.
  1988. result.error = -1;
  1989. } else if (url.path() ==
  1990. "/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx") {
  1991. download_metrics.url = url;
  1992. download_metrics.downloader = DownloadMetrics::kNone;
  1993. download_metrics.error = 0;
  1994. download_metrics.downloaded_bytes = 53855;
  1995. download_metrics.total_bytes = 53855;
  1996. download_metrics.download_time_ms = 1000;
  1997. EXPECT_TRUE(MakeTestFile(
  1998. TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), &path));
  1999. result.error = 0;
  2000. result.response = path;
  2001. }
  2002. base::ThreadTaskRunnerHandle::Get()->PostTask(
  2003. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  2004. base::Unretained(this),
  2005. download_metrics.downloaded_bytes,
  2006. download_metrics.total_bytes));
  2007. base::ThreadTaskRunnerHandle::Get()->PostTask(
  2008. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  2009. base::Unretained(this), true, result,
  2010. download_metrics));
  2011. }
  2012. };
  2013. class MockPingManager : public MockPingManagerImpl {
  2014. public:
  2015. explicit MockPingManager(scoped_refptr<Configurator> config)
  2016. : MockPingManagerImpl(config) {}
  2017. protected:
  2018. ~MockPingManager() override {
  2019. const auto ping_data = MockPingManagerImpl::ping_data();
  2020. EXPECT_EQ(2u, ping_data.size());
  2021. EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[0].id);
  2022. EXPECT_EQ(base::Version("0.8"), ping_data[0].previous_version);
  2023. EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
  2024. EXPECT_EQ(0, static_cast<int>(ping_data[0].error_category));
  2025. EXPECT_EQ(0, ping_data[0].error_code);
  2026. EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[1].id);
  2027. EXPECT_EQ(base::Version("1.0"), ping_data[1].previous_version);
  2028. EXPECT_EQ(base::Version("2.0"), ping_data[1].next_version);
  2029. EXPECT_EQ(0, static_cast<int>(ping_data[1].error_category));
  2030. EXPECT_EQ(0, ping_data[1].error_code);
  2031. EXPECT_TRUE(ping_data[1].diff_update_failed);
  2032. EXPECT_EQ(1, static_cast<int>(ping_data[1].diff_error_category));
  2033. EXPECT_EQ(-1, ping_data[1].diff_error_code);
  2034. }
  2035. };
  2036. SetMockCrxDownloader<MockCrxDownloader>();
  2037. scoped_refptr<UpdateClient> update_client =
  2038. base::MakeRefCounted<UpdateClientImpl>(
  2039. config(), base::MakeRefCounted<MockPingManager>(config()),
  2040. &MockUpdateChecker::Create);
  2041. MockObserver observer;
  2042. {
  2043. InSequence seq;
  2044. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  2045. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  2046. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  2047. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  2048. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  2049. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  2050. .Times(AtLeast(1));
  2051. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
  2052. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  2053. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
  2054. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  2055. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  2056. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  2057. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  2058. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  2059. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  2060. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  2061. .Times(AtLeast(1));
  2062. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
  2063. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  2064. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
  2065. "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
  2066. }
  2067. update_client->AddObserver(&observer);
  2068. const std::vector<std::string> ids = {"ihfokbkgjpifnbbojhneepfflplebdkc"};
  2069. {
  2070. std::vector<CrxUpdateItem> items;
  2071. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  2072. EXPECT_CALL(*receiver, Receive(_))
  2073. .WillRepeatedly(
  2074. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  2075. base::RunLoop runloop;
  2076. update_client->Update(
  2077. ids, base::BindOnce(&DataCallbackMock::Callback),
  2078. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  2079. false,
  2080. base::BindOnce(&CompletionCallbackMock::Callback,
  2081. runloop.QuitClosure()));
  2082. runloop.Run();
  2083. EXPECT_EQ(6u, items.size());
  2084. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  2085. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[0].id.c_str());
  2086. EXPECT_EQ(ComponentState::kCanUpdate, items[1].state);
  2087. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str());
  2088. EXPECT_EQ(ComponentState::kDownloading, items[2].state);
  2089. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[2].id.c_str());
  2090. EXPECT_EQ(ComponentState::kDownloading, items[3].state);
  2091. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[3].id.c_str());
  2092. EXPECT_EQ(ComponentState::kUpdating, items[4].state);
  2093. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[4].id.c_str());
  2094. EXPECT_EQ(ComponentState::kUpdated, items[5].state);
  2095. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[5].id.c_str());
  2096. }
  2097. {
  2098. std::vector<CrxUpdateItem> items;
  2099. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  2100. EXPECT_CALL(*receiver, Receive(_))
  2101. .WillRepeatedly(
  2102. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  2103. base::RunLoop runloop;
  2104. update_client->Update(
  2105. ids, base::BindOnce(&DataCallbackMock::Callback),
  2106. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  2107. false,
  2108. base::BindOnce(&CompletionCallbackMock::Callback,
  2109. runloop.QuitClosure()));
  2110. runloop.Run();
  2111. EXPECT_EQ(8u, items.size());
  2112. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  2113. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[0].id.c_str());
  2114. EXPECT_EQ(ComponentState::kCanUpdate, items[1].state);
  2115. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str());
  2116. EXPECT_EQ(ComponentState::kDownloadingDiff, items[2].state);
  2117. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[2].id.c_str());
  2118. EXPECT_EQ(ComponentState::kDownloadingDiff, items[3].state);
  2119. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[3].id.c_str());
  2120. EXPECT_EQ(ComponentState::kDownloading, items[4].state);
  2121. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[4].id.c_str());
  2122. EXPECT_EQ(ComponentState::kDownloading, items[5].state);
  2123. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[5].id.c_str());
  2124. EXPECT_EQ(ComponentState::kUpdating, items[6].state);
  2125. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[6].id.c_str());
  2126. EXPECT_EQ(ComponentState::kUpdated, items[7].state);
  2127. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[7].id.c_str());
  2128. }
  2129. update_client->RemoveObserver(&observer);
  2130. }
  2131. // Tests the queuing of update checks. In this scenario, two update checks are
  2132. // done for one CRX. The second update check call is queued up and will run
  2133. // after the first check has completed. The CRX has no updates.
  2134. TEST_F(UpdateClientTest, OneCrxNoUpdateQueuedCall) {
  2135. class DataCallbackMock {
  2136. public:
  2137. static std::vector<absl::optional<CrxComponent>> Callback(
  2138. const std::vector<std::string>& ids) {
  2139. CrxComponent crx;
  2140. crx.name = "test_jebg";
  2141. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  2142. crx.version = base::Version("0.9");
  2143. crx.installer = base::MakeRefCounted<TestInstaller>();
  2144. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  2145. return {crx};
  2146. }
  2147. };
  2148. class CompletionCallbackMock {
  2149. public:
  2150. static void Callback(base::OnceClosure quit_closure, Error error) {
  2151. static int num_call = 0;
  2152. ++num_call;
  2153. EXPECT_EQ(Error::NONE, error);
  2154. if (num_call == 2)
  2155. std::move(quit_closure).Run();
  2156. }
  2157. };
  2158. class MockUpdateChecker : public UpdateChecker {
  2159. public:
  2160. static std::unique_ptr<UpdateChecker> Create(
  2161. scoped_refptr<Configurator> config,
  2162. PersistedData* metadata) {
  2163. return std::make_unique<MockUpdateChecker>();
  2164. }
  2165. void CheckForUpdates(
  2166. scoped_refptr<UpdateContext> context,
  2167. const base::flat_map<std::string, std::string>& additional_attributes,
  2168. UpdateCheckCallback update_check_callback) override {
  2169. EXPECT_FALSE(context->session_id.empty());
  2170. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  2171. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  2172. EXPECT_EQ(id, context->components_to_check_for_updates.front());
  2173. EXPECT_EQ(1u, context->components.count(id));
  2174. auto& component = context->components.at(id);
  2175. EXPECT_FALSE(component->is_foreground());
  2176. ProtocolParser::Result result;
  2177. result.extension_id = id;
  2178. result.status = "noupdate";
  2179. ProtocolParser::Results results;
  2180. results.list.push_back(result);
  2181. base::ThreadTaskRunnerHandle::Get()->PostTask(
  2182. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  2183. ErrorCategory::kNone, 0, 0));
  2184. }
  2185. };
  2186. class MockCrxDownloader : public CrxDownloader {
  2187. public:
  2188. MockCrxDownloader() : CrxDownloader(nullptr) {}
  2189. private:
  2190. ~MockCrxDownloader() override = default;
  2191. void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
  2192. };
  2193. class MockPingManager : public MockPingManagerImpl {
  2194. public:
  2195. explicit MockPingManager(scoped_refptr<Configurator> config)
  2196. : MockPingManagerImpl(config) {}
  2197. protected:
  2198. ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
  2199. };
  2200. SetMockCrxDownloader<MockCrxDownloader>();
  2201. scoped_refptr<UpdateClient> update_client =
  2202. base::MakeRefCounted<UpdateClientImpl>(
  2203. config(), base::MakeRefCounted<MockPingManager>(config()),
  2204. &MockUpdateChecker::Create);
  2205. MockObserver observer;
  2206. {
  2207. InSequence seq;
  2208. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  2209. "jebgalgnebhfojomionfpkfelancnnkf"))
  2210. .Times(1);
  2211. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_ALREADY_UP_TO_DATE,
  2212. "jebgalgnebhfojomionfpkfelancnnkf"))
  2213. .Times(1);
  2214. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  2215. "jebgalgnebhfojomionfpkfelancnnkf"))
  2216. .Times(1);
  2217. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_ALREADY_UP_TO_DATE,
  2218. "jebgalgnebhfojomionfpkfelancnnkf"))
  2219. .Times(1);
  2220. }
  2221. std::vector<CrxUpdateItem> items1;
  2222. auto receiver1 = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  2223. EXPECT_CALL(*receiver1, Receive(_))
  2224. .WillRepeatedly(
  2225. [&items1](const CrxUpdateItem& item) { items1.push_back(item); });
  2226. std::vector<CrxUpdateItem> items2;
  2227. auto receiver2 = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  2228. EXPECT_CALL(*receiver2, Receive(_))
  2229. .WillRepeatedly(
  2230. [&items2](const CrxUpdateItem& item) { items2.push_back(item); });
  2231. update_client->AddObserver(&observer);
  2232. const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"};
  2233. update_client->Update(
  2234. ids, base::BindOnce(&DataCallbackMock::Callback),
  2235. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver1),
  2236. false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  2237. update_client->Update(
  2238. ids, base::BindOnce(&DataCallbackMock::Callback),
  2239. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver2),
  2240. false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  2241. RunThreads();
  2242. EXPECT_EQ(2u, items1.size());
  2243. EXPECT_EQ(ComponentState::kChecking, items1[0].state);
  2244. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items1[0].id.c_str());
  2245. EXPECT_EQ(ComponentState::kUpToDate, items1[1].state);
  2246. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items1[1].id.c_str());
  2247. EXPECT_EQ(2u, items2.size());
  2248. EXPECT_EQ(ComponentState::kChecking, items2[0].state);
  2249. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items2[0].id.c_str());
  2250. EXPECT_EQ(ComponentState::kUpToDate, items2[1].state);
  2251. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items2[1].id.c_str());
  2252. update_client->RemoveObserver(&observer);
  2253. }
  2254. // Tests the install of one CRX. Tests the installer is invoked with the
  2255. // run and arguments values of the manifest object. Tests that "pv" and "fp"
  2256. // are persisted.
  2257. TEST_F(UpdateClientTest, OneCrxInstall) {
  2258. class DataCallbackMock {
  2259. public:
  2260. static std::vector<absl::optional<CrxComponent>> Callback(
  2261. const std::vector<std::string>& ids) {
  2262. CrxComponent crx;
  2263. crx.name = "test_jebg";
  2264. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  2265. crx.version = base::Version("0.0");
  2266. crx.installer = base::MakeRefCounted<TestInstaller>();
  2267. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  2268. return {crx};
  2269. }
  2270. };
  2271. class CompletionCallbackMock {
  2272. public:
  2273. static void Callback(base::OnceClosure quit_closure, Error error) {
  2274. EXPECT_EQ(Error::NONE, error);
  2275. std::move(quit_closure).Run();
  2276. }
  2277. };
  2278. class MockUpdateChecker : public UpdateChecker {
  2279. public:
  2280. static std::unique_ptr<UpdateChecker> Create(
  2281. scoped_refptr<Configurator> config,
  2282. PersistedData* metadata) {
  2283. return std::make_unique<MockUpdateChecker>();
  2284. }
  2285. void CheckForUpdates(
  2286. scoped_refptr<UpdateContext> context,
  2287. const base::flat_map<std::string, std::string>& additional_attributes,
  2288. UpdateCheckCallback update_check_callback) override {
  2289. /*
  2290. Mock the following response:
  2291. <?xml version='1.0' encoding='UTF-8'?>
  2292. <response protocol='3.1'>
  2293. <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
  2294. <updatecheck status='ok'>
  2295. <urls>
  2296. <url codebase='http://localhost/download/'/>
  2297. </urls>
  2298. <manifest version='1.0' prodversionmin='11.0.1.0'
  2299. run='UpdaterSetup.exe' arguments='--arg1 --arg2'>
  2300. <packages>
  2301. <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
  2302. hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
  2303. a284a7cd8059c3409ce0498'/>
  2304. </packages>
  2305. </manifest>
  2306. </updatecheck>
  2307. </app>
  2308. </response>
  2309. */
  2310. EXPECT_FALSE(context->session_id.empty());
  2311. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  2312. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  2313. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  2314. EXPECT_EQ(1u, context->components.count(id));
  2315. ProtocolParser::Result::Manifest::Package package;
  2316. package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
  2317. package.hash_sha256 =
  2318. "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
  2319. package.fingerprint = "some-fingerprint";
  2320. ProtocolParser::Result result;
  2321. result.extension_id = id;
  2322. result.status = "ok";
  2323. result.crx_urls.push_back(GURL("http://localhost/download/"));
  2324. result.manifest.version = "1.0";
  2325. result.manifest.browser_min_version = "11.0.1.0";
  2326. result.manifest.run = "UpdaterSetup.exe";
  2327. result.manifest.arguments = "--arg1 --arg2";
  2328. result.manifest.packages.push_back(package);
  2329. ProtocolParser::Results results;
  2330. results.list.push_back(result);
  2331. // Verify that calling Install sets ondemand.
  2332. EXPECT_TRUE(context->components.at(id)->is_foreground());
  2333. base::ThreadTaskRunnerHandle::Get()->PostTask(
  2334. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  2335. ErrorCategory::kNone, 0, 0));
  2336. }
  2337. };
  2338. class MockCrxDownloader : public CrxDownloader {
  2339. public:
  2340. MockCrxDownloader() : CrxDownloader(nullptr) {}
  2341. private:
  2342. ~MockCrxDownloader() override = default;
  2343. void DoStartDownload(const GURL& url) override {
  2344. DownloadMetrics download_metrics;
  2345. FilePath path;
  2346. Result result;
  2347. if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") {
  2348. download_metrics.url = url;
  2349. download_metrics.downloader = DownloadMetrics::kNone;
  2350. download_metrics.error = 0;
  2351. download_metrics.downloaded_bytes = 1843;
  2352. download_metrics.total_bytes = 1843;
  2353. download_metrics.download_time_ms = 1000;
  2354. EXPECT_TRUE(MakeTestFile(
  2355. TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
  2356. result.error = 0;
  2357. result.response = path;
  2358. } else {
  2359. NOTREACHED();
  2360. }
  2361. base::ThreadTaskRunnerHandle::Get()->PostTask(
  2362. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  2363. base::Unretained(this),
  2364. download_metrics.downloaded_bytes,
  2365. download_metrics.total_bytes));
  2366. base::ThreadTaskRunnerHandle::Get()->PostTask(
  2367. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  2368. base::Unretained(this), true, result,
  2369. download_metrics));
  2370. }
  2371. };
  2372. class MockPingManager : public MockPingManagerImpl {
  2373. public:
  2374. explicit MockPingManager(scoped_refptr<Configurator> config)
  2375. : MockPingManagerImpl(config) {}
  2376. protected:
  2377. ~MockPingManager() override {
  2378. const auto ping_data = MockPingManagerImpl::ping_data();
  2379. EXPECT_EQ(1u, ping_data.size());
  2380. EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
  2381. EXPECT_EQ(base::Version("0.0"), ping_data[0].previous_version);
  2382. EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
  2383. EXPECT_EQ(0, static_cast<int>(ping_data[0].error_category));
  2384. EXPECT_EQ(0, ping_data[0].error_code);
  2385. }
  2386. };
  2387. SetMockCrxDownloader<MockCrxDownloader>();
  2388. scoped_refptr<UpdateClient> update_client =
  2389. base::MakeRefCounted<UpdateClientImpl>(
  2390. config(), base::MakeRefCounted<MockPingManager>(config()),
  2391. &MockUpdateChecker::Create);
  2392. {
  2393. EXPECT_FALSE(config()->GetPrefService()->FindPreference(
  2394. "updateclientdata.apps.jebgalgnebhfojomionfpkfelancnnkf.pv"));
  2395. EXPECT_FALSE(config()->GetPrefService()->FindPreference(
  2396. "updateclientdata.apps.jebgalgnebhfojomionfpkfelancnnkf.fp"));
  2397. }
  2398. MockObserver observer;
  2399. {
  2400. InSequence seq;
  2401. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  2402. "jebgalgnebhfojomionfpkfelancnnkf"))
  2403. .Times(1);
  2404. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  2405. "jebgalgnebhfojomionfpkfelancnnkf"))
  2406. .Times(1);
  2407. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  2408. "jebgalgnebhfojomionfpkfelancnnkf"))
  2409. .Times(AtLeast(1));
  2410. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
  2411. "jebgalgnebhfojomionfpkfelancnnkf"))
  2412. .Times(1);
  2413. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
  2414. "jebgalgnebhfojomionfpkfelancnnkf"))
  2415. .Times(1)
  2416. .WillOnce(Invoke([update_client](Events event, const std::string& id) {
  2417. CrxUpdateItem update_item;
  2418. ASSERT_TRUE(update_client->GetCrxUpdateState(id, &update_item));
  2419. ASSERT_TRUE(update_item.component);
  2420. const auto* test_installer = static_cast<TestInstaller*>(
  2421. update_item.component->installer.get());
  2422. EXPECT_STREQ("UpdaterSetup.exe",
  2423. test_installer->install_params()->run.c_str());
  2424. EXPECT_STREQ("--arg1 --arg2",
  2425. test_installer->install_params()->arguments.c_str());
  2426. }));
  2427. }
  2428. std::vector<CrxUpdateItem> items;
  2429. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  2430. EXPECT_CALL(*receiver, Receive(_))
  2431. .WillRepeatedly(
  2432. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  2433. update_client->AddObserver(&observer);
  2434. update_client->Install(
  2435. std::string("jebgalgnebhfojomionfpkfelancnnkf"),
  2436. base::BindOnce(&DataCallbackMock::Callback),
  2437. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  2438. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  2439. RunThreads();
  2440. EXPECT_EQ(6u, items.size());
  2441. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  2442. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  2443. EXPECT_EQ(ComponentState::kCanUpdate, items[1].state);
  2444. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[1].id.c_str());
  2445. EXPECT_EQ(ComponentState::kDownloading, items[2].state);
  2446. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str());
  2447. EXPECT_EQ(ComponentState::kDownloading, items[3].state);
  2448. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str());
  2449. EXPECT_EQ(ComponentState::kUpdating, items[4].state);
  2450. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str());
  2451. EXPECT_EQ(ComponentState::kUpdated, items[5].state);
  2452. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[5].id.c_str());
  2453. const base::Value::Dict& dict =
  2454. config()->GetPrefService()->GetValueDict("updateclientdata");
  2455. const std::string* pv =
  2456. dict.FindStringByDottedPath("apps.jebgalgnebhfojomionfpkfelancnnkf.pv");
  2457. ASSERT_TRUE(pv);
  2458. EXPECT_STREQ("1.0", pv->c_str());
  2459. const std::string* fingerprint =
  2460. dict.FindStringByDottedPath("apps.jebgalgnebhfojomionfpkfelancnnkf.fp");
  2461. ASSERT_TRUE(fingerprint);
  2462. EXPECT_STREQ("some-fingerprint", fingerprint->c_str());
  2463. update_client->RemoveObserver(&observer);
  2464. }
  2465. // Tests the install of one CRX when no component data is provided. This
  2466. // results in an install error.
  2467. TEST_F(UpdateClientTest, OneCrxInstallNoCrxComponentData) {
  2468. class DataCallbackMock {
  2469. public:
  2470. static std::vector<absl::optional<CrxComponent>> Callback(
  2471. const std::vector<std::string>& ids) {
  2472. return {absl::nullopt};
  2473. }
  2474. };
  2475. class CompletionCallbackMock {
  2476. public:
  2477. static void Callback(base::OnceClosure quit_closure, Error error) {
  2478. EXPECT_EQ(Error::NONE, error);
  2479. std::move(quit_closure).Run();
  2480. }
  2481. };
  2482. class MockUpdateChecker : public UpdateChecker {
  2483. public:
  2484. static std::unique_ptr<UpdateChecker> Create(
  2485. scoped_refptr<Configurator> config,
  2486. PersistedData* metadata) {
  2487. return std::make_unique<MockUpdateChecker>();
  2488. }
  2489. void CheckForUpdates(
  2490. scoped_refptr<UpdateContext> context,
  2491. const base::flat_map<std::string, std::string>& additional_attributes,
  2492. UpdateCheckCallback update_check_callback) override {
  2493. NOTREACHED();
  2494. }
  2495. };
  2496. class MockCrxDownloader : public CrxDownloader {
  2497. public:
  2498. MockCrxDownloader() : CrxDownloader(nullptr) {}
  2499. private:
  2500. ~MockCrxDownloader() override = default;
  2501. void DoStartDownload(const GURL& url) override { NOTREACHED(); }
  2502. };
  2503. class MockPingManager : public MockPingManagerImpl {
  2504. public:
  2505. explicit MockPingManager(scoped_refptr<Configurator> config)
  2506. : MockPingManagerImpl(config) {}
  2507. protected:
  2508. ~MockPingManager() override {
  2509. EXPECT_EQ(0u, MockPingManagerImpl::ping_data().size());
  2510. }
  2511. };
  2512. SetMockCrxDownloader<MockCrxDownloader>();
  2513. scoped_refptr<UpdateClient> update_client =
  2514. base::MakeRefCounted<UpdateClientImpl>(
  2515. config(), base::MakeRefCounted<MockPingManager>(config()),
  2516. &MockUpdateChecker::Create);
  2517. MockObserver observer;
  2518. {
  2519. InSequence seq;
  2520. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  2521. "jebgalgnebhfojomionfpkfelancnnkf"))
  2522. .Times(1)
  2523. .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
  2524. // Tests that the state of the component when the CrxComponent data
  2525. // is not provided. In this case, the optional |item.component|
  2526. // instance is not present.
  2527. CrxUpdateItem item;
  2528. EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
  2529. EXPECT_EQ(ComponentState::kUpdateError, item.state);
  2530. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", item.id.c_str());
  2531. EXPECT_FALSE(item.component);
  2532. EXPECT_EQ(ErrorCategory::kService, item.error_category);
  2533. EXPECT_EQ(static_cast<int>(Error::CRX_NOT_FOUND), item.error_code);
  2534. EXPECT_EQ(0, item.extra_code1);
  2535. }));
  2536. }
  2537. std::vector<CrxUpdateItem> items;
  2538. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  2539. EXPECT_CALL(*receiver, Receive(_))
  2540. .WillRepeatedly(
  2541. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  2542. update_client->AddObserver(&observer);
  2543. update_client->Install(
  2544. std::string("jebgalgnebhfojomionfpkfelancnnkf"),
  2545. base::BindOnce(&DataCallbackMock::Callback),
  2546. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  2547. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  2548. RunThreads();
  2549. EXPECT_EQ(1u, items.size());
  2550. EXPECT_EQ(ComponentState::kUpdateError, items[0].state);
  2551. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  2552. update_client->RemoveObserver(&observer);
  2553. }
  2554. // Tests that overlapping installs of the same CRX result in an error.
  2555. TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) {
  2556. class DataCallbackMock {
  2557. public:
  2558. static std::vector<absl::optional<CrxComponent>> Callback(
  2559. const std::vector<std::string>& ids) {
  2560. CrxComponent crx;
  2561. crx.name = "test_jebg";
  2562. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  2563. crx.version = base::Version("0.0");
  2564. crx.installer = base::MakeRefCounted<TestInstaller>();
  2565. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  2566. return {crx};
  2567. }
  2568. };
  2569. class CompletionCallbackMock {
  2570. public:
  2571. static void Callback(base::OnceClosure quit_closure, Error error) {
  2572. static int num_call = 0;
  2573. ++num_call;
  2574. EXPECT_LE(num_call, 2);
  2575. if (num_call == 1) {
  2576. EXPECT_EQ(Error::UPDATE_IN_PROGRESS, error);
  2577. return;
  2578. }
  2579. if (num_call == 2) {
  2580. EXPECT_EQ(Error::NONE, error);
  2581. std::move(quit_closure).Run();
  2582. }
  2583. }
  2584. };
  2585. class MockUpdateChecker : public UpdateChecker {
  2586. public:
  2587. static std::unique_ptr<UpdateChecker> Create(
  2588. scoped_refptr<Configurator> config,
  2589. PersistedData* metadata) {
  2590. return std::make_unique<MockUpdateChecker>();
  2591. }
  2592. void CheckForUpdates(
  2593. scoped_refptr<UpdateContext> context,
  2594. const base::flat_map<std::string, std::string>& additional_attributes,
  2595. UpdateCheckCallback update_check_callback) override {
  2596. EXPECT_FALSE(context->session_id.empty());
  2597. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  2598. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  2599. EXPECT_EQ(id, context->components_to_check_for_updates.front());
  2600. EXPECT_EQ(1u, context->components.count(id));
  2601. ProtocolParser::Result result;
  2602. result.extension_id = id;
  2603. result.status = "noupdate";
  2604. ProtocolParser::Results results;
  2605. results.list.push_back(result);
  2606. // Verify that calling Install sets |is_foreground| for the component.
  2607. EXPECT_TRUE(context->components.at(id)->is_foreground());
  2608. base::ThreadTaskRunnerHandle::Get()->PostTask(
  2609. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  2610. ErrorCategory::kNone, 0, 0));
  2611. }
  2612. };
  2613. class MockCrxDownloader : public CrxDownloader {
  2614. public:
  2615. MockCrxDownloader() : CrxDownloader(nullptr) {}
  2616. private:
  2617. ~MockCrxDownloader() override = default;
  2618. void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
  2619. };
  2620. class MockPingManager : public MockPingManagerImpl {
  2621. public:
  2622. explicit MockPingManager(scoped_refptr<Configurator> config)
  2623. : MockPingManagerImpl(config) {}
  2624. protected:
  2625. ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
  2626. };
  2627. SetMockCrxDownloader<MockCrxDownloader>();
  2628. scoped_refptr<UpdateClient> update_client =
  2629. base::MakeRefCounted<UpdateClientImpl>(
  2630. config(), base::MakeRefCounted<MockPingManager>(config()),
  2631. &MockUpdateChecker::Create);
  2632. MockObserver observer;
  2633. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  2634. "jebgalgnebhfojomionfpkfelancnnkf"))
  2635. .Times(1);
  2636. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_ALREADY_UP_TO_DATE,
  2637. "jebgalgnebhfojomionfpkfelancnnkf"))
  2638. .Times(1);
  2639. std::vector<CrxUpdateItem> items1;
  2640. auto receiver1 = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  2641. EXPECT_CALL(*receiver1, Receive(_))
  2642. .WillRepeatedly(
  2643. [&items1](const CrxUpdateItem& item) { items1.push_back(item); });
  2644. std::vector<CrxUpdateItem> items2;
  2645. auto receiver2 = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  2646. EXPECT_CALL(*receiver2, Receive(_))
  2647. .WillRepeatedly(
  2648. [&items2](const CrxUpdateItem& item) { items2.push_back(item); });
  2649. update_client->AddObserver(&observer);
  2650. update_client->Install(
  2651. std::string("jebgalgnebhfojomionfpkfelancnnkf"),
  2652. base::BindOnce(&DataCallbackMock::Callback),
  2653. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver1),
  2654. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  2655. update_client->Install(
  2656. std::string("jebgalgnebhfojomionfpkfelancnnkf"),
  2657. base::BindOnce(&DataCallbackMock::Callback),
  2658. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver2),
  2659. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  2660. RunThreads();
  2661. EXPECT_EQ(2u, items1.size());
  2662. EXPECT_EQ(ComponentState::kChecking, items1[0].state);
  2663. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items1[0].id.c_str());
  2664. EXPECT_EQ(ComponentState::kUpToDate, items1[1].state);
  2665. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items1[1].id.c_str());
  2666. EXPECT_TRUE(items2.empty());
  2667. update_client->RemoveObserver(&observer);
  2668. }
  2669. // Tests that UpdateClient::Update returns Error::INVALID_ARGUMENT when
  2670. // the |ids| parameter is empty.
  2671. TEST_F(UpdateClientTest, EmptyIdList) {
  2672. class DataCallbackMock {
  2673. public:
  2674. static std::vector<absl::optional<CrxComponent>> Callback(
  2675. const std::vector<std::string>& ids) {
  2676. return {};
  2677. }
  2678. };
  2679. class CompletionCallbackMock {
  2680. public:
  2681. static void Callback(base::OnceClosure quit_closure, Error error) {
  2682. EXPECT_EQ(Error::INVALID_ARGUMENT, error);
  2683. std::move(quit_closure).Run();
  2684. }
  2685. };
  2686. class MockUpdateChecker : public UpdateChecker {
  2687. public:
  2688. static std::unique_ptr<UpdateChecker> Create(
  2689. scoped_refptr<Configurator> config,
  2690. PersistedData* metadata) {
  2691. return std::make_unique<MockUpdateChecker>();
  2692. }
  2693. void CheckForUpdates(
  2694. scoped_refptr<UpdateContext> context,
  2695. const base::flat_map<std::string, std::string>& additional_attributes,
  2696. UpdateCheckCallback update_check_callback) override {
  2697. NOTREACHED();
  2698. }
  2699. };
  2700. class MockCrxDownloader : public CrxDownloader {
  2701. public:
  2702. MockCrxDownloader() : CrxDownloader(nullptr) {}
  2703. private:
  2704. ~MockCrxDownloader() override = default;
  2705. void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
  2706. };
  2707. class MockPingManager : public MockPingManagerImpl {
  2708. public:
  2709. explicit MockPingManager(scoped_refptr<Configurator> config)
  2710. : MockPingManagerImpl(config) {}
  2711. protected:
  2712. ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
  2713. };
  2714. SetMockCrxDownloader<MockCrxDownloader>();
  2715. scoped_refptr<UpdateClient> update_client =
  2716. base::MakeRefCounted<UpdateClientImpl>(
  2717. config(), base::MakeRefCounted<MockPingManager>(config()),
  2718. &MockUpdateChecker::Create);
  2719. const std::vector<std::string> empty_id_list;
  2720. update_client->Update(
  2721. empty_id_list, base::BindOnce(&DataCallbackMock::Callback), {}, false,
  2722. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  2723. RunThreads();
  2724. }
  2725. TEST_F(UpdateClientTest, SendUninstallPing) {
  2726. class CompletionCallbackMock {
  2727. public:
  2728. static void Callback(base::OnceClosure quit_closure, Error error) {
  2729. std::move(quit_closure).Run();
  2730. }
  2731. };
  2732. class MockUpdateChecker : public UpdateChecker {
  2733. public:
  2734. static std::unique_ptr<UpdateChecker> Create(
  2735. scoped_refptr<Configurator> config,
  2736. PersistedData* metadata) {
  2737. return nullptr;
  2738. }
  2739. void CheckForUpdates(
  2740. scoped_refptr<UpdateContext> context,
  2741. const base::flat_map<std::string, std::string>& additional_attributes,
  2742. UpdateCheckCallback update_check_callback) override {
  2743. NOTREACHED();
  2744. }
  2745. };
  2746. class MockCrxDownloader : public CrxDownloader {
  2747. public:
  2748. static scoped_refptr<CrxDownloader> Create(
  2749. bool is_background_download,
  2750. scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
  2751. return nullptr;
  2752. }
  2753. MockCrxDownloader() : CrxDownloader(nullptr) {}
  2754. private:
  2755. ~MockCrxDownloader() override = default;
  2756. void DoStartDownload(const GURL& url) override {}
  2757. };
  2758. class MockPingManager : public MockPingManagerImpl {
  2759. public:
  2760. explicit MockPingManager(scoped_refptr<Configurator> config)
  2761. : MockPingManagerImpl(config) {}
  2762. protected:
  2763. ~MockPingManager() override {
  2764. const auto ping_data = MockPingManagerImpl::ping_data();
  2765. EXPECT_EQ(1u, ping_data.size());
  2766. EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
  2767. EXPECT_EQ(base::Version("1.2.3.4"), ping_data[0].previous_version);
  2768. EXPECT_EQ(base::Version("0"), ping_data[0].next_version);
  2769. EXPECT_EQ(10, ping_data[0].extra_code1);
  2770. }
  2771. };
  2772. SetMockCrxDownloader<MockCrxDownloader>();
  2773. scoped_refptr<UpdateClient> update_client =
  2774. base::MakeRefCounted<UpdateClientImpl>(
  2775. config(), base::MakeRefCounted<MockPingManager>(config()),
  2776. &MockUpdateChecker::Create);
  2777. CrxComponent crx;
  2778. crx.app_id = "jebgalgnebhfojomionfpkfelancnnkf";
  2779. crx.version = base::Version("1.2.3.4");
  2780. update_client->SendUninstallPing(
  2781. crx, 10,
  2782. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  2783. RunThreads();
  2784. }
  2785. TEST_F(UpdateClientTest, RetryAfter) {
  2786. class DataCallbackMock {
  2787. public:
  2788. static std::vector<absl::optional<CrxComponent>> Callback(
  2789. const std::vector<std::string>& ids) {
  2790. CrxComponent crx;
  2791. crx.name = "test_jebg";
  2792. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  2793. crx.version = base::Version("0.9");
  2794. crx.installer = base::MakeRefCounted<TestInstaller>();
  2795. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  2796. return {crx};
  2797. }
  2798. };
  2799. class CompletionCallbackMock {
  2800. public:
  2801. static void Callback(base::OnceClosure quit_closure, Error error) {
  2802. static int num_call = 0;
  2803. ++num_call;
  2804. EXPECT_LE(num_call, 4);
  2805. if (num_call == 1) {
  2806. EXPECT_EQ(Error::NONE, error);
  2807. } else if (num_call == 2) {
  2808. // This request is throttled since the update engine received a
  2809. // positive |retry_after_sec| value in the update check response.
  2810. EXPECT_EQ(Error::RETRY_LATER, error);
  2811. } else if (num_call == 3) {
  2812. // This request is a foreground Install, which is never throttled.
  2813. // The update engine received a |retry_after_sec| value of 0, which
  2814. // resets the throttling.
  2815. EXPECT_EQ(Error::NONE, error);
  2816. } else if (num_call == 4) {
  2817. // This request succeeds since there is no throttling in effect.
  2818. EXPECT_EQ(Error::NONE, error);
  2819. }
  2820. std::move(quit_closure).Run();
  2821. }
  2822. };
  2823. class MockUpdateChecker : public UpdateChecker {
  2824. public:
  2825. static std::unique_ptr<UpdateChecker> Create(
  2826. scoped_refptr<Configurator> config,
  2827. PersistedData* metadata) {
  2828. return std::make_unique<MockUpdateChecker>();
  2829. }
  2830. void CheckForUpdates(
  2831. scoped_refptr<UpdateContext> context,
  2832. const base::flat_map<std::string, std::string>& additional_attributes,
  2833. UpdateCheckCallback update_check_callback) override {
  2834. EXPECT_FALSE(context->session_id.empty());
  2835. static int num_call = 0;
  2836. ++num_call;
  2837. EXPECT_LE(num_call, 3);
  2838. int retry_after_sec(0);
  2839. if (num_call == 1) {
  2840. // Throttle the next call.
  2841. retry_after_sec = 60 * 60; // 1 hour.
  2842. }
  2843. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  2844. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  2845. EXPECT_EQ(id, context->components_to_check_for_updates.front());
  2846. EXPECT_EQ(1u, context->components.count(id));
  2847. ProtocolParser::Result result;
  2848. result.extension_id = id;
  2849. result.status = "noupdate";
  2850. ProtocolParser::Results results;
  2851. results.list.push_back(result);
  2852. base::ThreadTaskRunnerHandle::Get()->PostTask(
  2853. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  2854. ErrorCategory::kNone, 0, retry_after_sec));
  2855. }
  2856. };
  2857. class MockCrxDownloader : public CrxDownloader {
  2858. public:
  2859. MockCrxDownloader() : CrxDownloader(nullptr) {}
  2860. private:
  2861. ~MockCrxDownloader() override = default;
  2862. void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
  2863. };
  2864. class MockPingManager : public MockPingManagerImpl {
  2865. public:
  2866. explicit MockPingManager(scoped_refptr<Configurator> config)
  2867. : MockPingManagerImpl(config) {}
  2868. protected:
  2869. ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
  2870. };
  2871. SetMockCrxDownloader<MockCrxDownloader>();
  2872. scoped_refptr<UpdateClient> update_client =
  2873. base::MakeRefCounted<UpdateClientImpl>(
  2874. config(), base::MakeRefCounted<MockPingManager>(config()),
  2875. &MockUpdateChecker::Create);
  2876. MockObserver observer;
  2877. InSequence seq;
  2878. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  2879. "jebgalgnebhfojomionfpkfelancnnkf"))
  2880. .Times(1);
  2881. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_ALREADY_UP_TO_DATE,
  2882. "jebgalgnebhfojomionfpkfelancnnkf"))
  2883. .Times(1);
  2884. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  2885. "jebgalgnebhfojomionfpkfelancnnkf"))
  2886. .Times(1);
  2887. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_ALREADY_UP_TO_DATE,
  2888. "jebgalgnebhfojomionfpkfelancnnkf"))
  2889. .Times(1);
  2890. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  2891. "jebgalgnebhfojomionfpkfelancnnkf"))
  2892. .Times(1);
  2893. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_ALREADY_UP_TO_DATE,
  2894. "jebgalgnebhfojomionfpkfelancnnkf"))
  2895. .Times(1);
  2896. update_client->AddObserver(&observer);
  2897. const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"};
  2898. {
  2899. // The engine handles this Update call but responds with a valid
  2900. // |retry_after_sec|, which causes subsequent calls to fail.
  2901. base::RunLoop runloop;
  2902. update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), {},
  2903. false,
  2904. base::BindOnce(&CompletionCallbackMock::Callback,
  2905. runloop.QuitClosure()));
  2906. runloop.Run();
  2907. }
  2908. {
  2909. // This call will result in a completion callback invoked with
  2910. // Error::ERROR_UPDATE_RETRY_LATER.
  2911. base::RunLoop runloop;
  2912. update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), {},
  2913. false,
  2914. base::BindOnce(&CompletionCallbackMock::Callback,
  2915. runloop.QuitClosure()));
  2916. runloop.Run();
  2917. }
  2918. {
  2919. // The Install call is handled, and the throttling is reset due to
  2920. // the value of |retry_after_sec| in the completion callback.
  2921. base::RunLoop runloop;
  2922. update_client->Install(std::string("jebgalgnebhfojomionfpkfelancnnkf"),
  2923. base::BindOnce(&DataCallbackMock::Callback), {},
  2924. base::BindOnce(&CompletionCallbackMock::Callback,
  2925. runloop.QuitClosure()));
  2926. runloop.Run();
  2927. }
  2928. {
  2929. // This call succeeds.
  2930. base::RunLoop runloop;
  2931. update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback), {},
  2932. false,
  2933. base::BindOnce(&CompletionCallbackMock::Callback,
  2934. runloop.QuitClosure()));
  2935. runloop.Run();
  2936. }
  2937. update_client->RemoveObserver(&observer);
  2938. }
  2939. // Tests the update check for two CRXs scenario. The first component supports
  2940. // the group policy to enable updates, and has its updates disabled. The second
  2941. // component has an update. The server does not honor the "updatedisabled"
  2942. // attribute and returns updates for both components. However, the update for
  2943. // the first component is not applied and the client responds with a
  2944. // (SERVICE_ERROR, UPDATE_DISABLED)
  2945. TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
  2946. class DataCallbackMock {
  2947. public:
  2948. static std::vector<absl::optional<CrxComponent>> Callback(
  2949. const std::vector<std::string>& ids) {
  2950. CrxComponent crx1;
  2951. crx1.name = "test_jebg";
  2952. crx1.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  2953. crx1.version = base::Version("0.9");
  2954. crx1.installer = base::MakeRefCounted<TestInstaller>();
  2955. crx1.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  2956. crx1.updates_enabled = false;
  2957. CrxComponent crx2;
  2958. crx2.name = "test_ihfo";
  2959. crx2.pk_hash.assign(ihfo_hash, ihfo_hash + std::size(ihfo_hash));
  2960. crx2.version = base::Version("0.8");
  2961. crx2.installer = base::MakeRefCounted<TestInstaller>();
  2962. crx2.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  2963. return {crx1, crx2};
  2964. }
  2965. };
  2966. class CompletionCallbackMock {
  2967. public:
  2968. static void Callback(base::OnceClosure quit_closure, Error error) {
  2969. EXPECT_EQ(Error::NONE, error);
  2970. std::move(quit_closure).Run();
  2971. }
  2972. };
  2973. class MockUpdateChecker : public UpdateChecker {
  2974. public:
  2975. static std::unique_ptr<UpdateChecker> Create(
  2976. scoped_refptr<Configurator> config,
  2977. PersistedData* metadata) {
  2978. return std::make_unique<MockUpdateChecker>();
  2979. }
  2980. void CheckForUpdates(
  2981. scoped_refptr<UpdateContext> context,
  2982. const base::flat_map<std::string, std::string>& additional_attributes,
  2983. UpdateCheckCallback update_check_callback) override {
  2984. /*
  2985. Mock the following response:
  2986. <?xml version='1.0' encoding='UTF-8'?>
  2987. <response protocol='3.1'>
  2988. <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
  2989. <updatecheck status='ok'>
  2990. <urls>
  2991. <url codebase='http://localhost/download/'/>
  2992. </urls>
  2993. <manifest version='1.0' prodversionmin='11.0.1.0'>
  2994. <packages>
  2995. <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
  2996. hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
  2997. a284a7cd8059c3409ce0498'/>
  2998. </packages>
  2999. </manifest>
  3000. </updatecheck>
  3001. </app>
  3002. <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
  3003. <updatecheck status='ok'>
  3004. <urls>
  3005. <url codebase='http://localhost/download/'/>
  3006. </urls>
  3007. <manifest version='1.0' prodversionmin='11.0.1.0'>
  3008. <packages>
  3009. <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'
  3010. hash_sha256='8f5aa190311237cae00675af87ff457f278cd1a05
  3011. 895470ac5d46647d4a3c2ea'/>
  3012. </packages>
  3013. </manifest>
  3014. </updatecheck>
  3015. </app>
  3016. </response>
  3017. */
  3018. EXPECT_FALSE(context->session_id.empty());
  3019. EXPECT_EQ(2u, context->components_to_check_for_updates.size());
  3020. ProtocolParser::Results results;
  3021. {
  3022. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  3023. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  3024. EXPECT_EQ(1u, context->components.count(id));
  3025. ProtocolParser::Result::Manifest::Package package;
  3026. package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
  3027. package.hash_sha256 =
  3028. "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
  3029. ProtocolParser::Result result;
  3030. result.extension_id = id;
  3031. result.status = "ok";
  3032. result.crx_urls.push_back(GURL("http://localhost/download/"));
  3033. result.manifest.version = "1.0";
  3034. result.manifest.browser_min_version = "11.0.1.0";
  3035. result.manifest.packages.push_back(package);
  3036. results.list.push_back(result);
  3037. }
  3038. {
  3039. const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
  3040. EXPECT_EQ(id, context->components_to_check_for_updates[1]);
  3041. EXPECT_EQ(1u, context->components.count(id));
  3042. ProtocolParser::Result::Manifest::Package package;
  3043. package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
  3044. package.hash_sha256 =
  3045. "8f5aa190311237cae00675af87ff457f278cd1a05895470ac5d46647d4a3c2ea";
  3046. ProtocolParser::Result result;
  3047. result.extension_id = id;
  3048. result.status = "ok";
  3049. result.crx_urls.push_back(GURL("http://localhost/download/"));
  3050. result.manifest.version = "1.0";
  3051. result.manifest.browser_min_version = "11.0.1.0";
  3052. result.manifest.packages.push_back(package);
  3053. results.list.push_back(result);
  3054. }
  3055. base::ThreadTaskRunnerHandle::Get()->PostTask(
  3056. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  3057. ErrorCategory::kNone, 0, 0));
  3058. }
  3059. };
  3060. class MockCrxDownloader : public CrxDownloader {
  3061. public:
  3062. MockCrxDownloader() : CrxDownloader(nullptr) {}
  3063. private:
  3064. ~MockCrxDownloader() override = default;
  3065. void DoStartDownload(const GURL& url) override {
  3066. DownloadMetrics download_metrics;
  3067. FilePath path;
  3068. Result result;
  3069. if (url.path() == "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
  3070. download_metrics.url = url;
  3071. download_metrics.downloader = DownloadMetrics::kNone;
  3072. download_metrics.error = 0;
  3073. download_metrics.downloaded_bytes = 53638;
  3074. download_metrics.total_bytes = 53638;
  3075. download_metrics.download_time_ms = 2000;
  3076. EXPECT_TRUE(MakeTestFile(
  3077. TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
  3078. result.error = 0;
  3079. result.response = path;
  3080. } else {
  3081. NOTREACHED();
  3082. }
  3083. base::ThreadTaskRunnerHandle::Get()->PostTask(
  3084. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  3085. base::Unretained(this),
  3086. download_metrics.downloaded_bytes,
  3087. download_metrics.total_bytes));
  3088. base::ThreadTaskRunnerHandle::Get()->PostTask(
  3089. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  3090. base::Unretained(this), true, result,
  3091. download_metrics));
  3092. }
  3093. };
  3094. class MockPingManager : public MockPingManagerImpl {
  3095. public:
  3096. explicit MockPingManager(scoped_refptr<Configurator> config)
  3097. : MockPingManagerImpl(config) {}
  3098. protected:
  3099. ~MockPingManager() override {
  3100. const auto ping_data = MockPingManagerImpl::ping_data();
  3101. EXPECT_EQ(2u, ping_data.size());
  3102. EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
  3103. EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
  3104. EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
  3105. EXPECT_EQ(4, static_cast<int>(ping_data[0].error_category));
  3106. EXPECT_EQ(2, ping_data[0].error_code);
  3107. EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[1].id);
  3108. EXPECT_EQ(base::Version("0.8"), ping_data[1].previous_version);
  3109. EXPECT_EQ(base::Version("1.0"), ping_data[1].next_version);
  3110. EXPECT_EQ(0, static_cast<int>(ping_data[1].error_category));
  3111. EXPECT_EQ(0, ping_data[1].error_code);
  3112. }
  3113. };
  3114. // Disables updates for the components declaring support for the group policy.
  3115. SetMockCrxDownloader<MockCrxDownloader>();
  3116. scoped_refptr<UpdateClient> update_client =
  3117. base::MakeRefCounted<UpdateClientImpl>(
  3118. config(), base::MakeRefCounted<MockPingManager>(config()),
  3119. &MockUpdateChecker::Create);
  3120. MockObserver observer;
  3121. {
  3122. InSequence seq;
  3123. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  3124. "jebgalgnebhfojomionfpkfelancnnkf"))
  3125. .Times(1);
  3126. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  3127. "jebgalgnebhfojomionfpkfelancnnkf"))
  3128. .Times(1);
  3129. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  3130. "jebgalgnebhfojomionfpkfelancnnkf"))
  3131. .Times(1);
  3132. }
  3133. {
  3134. InSequence seq;
  3135. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  3136. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  3137. .Times(1);
  3138. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  3139. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  3140. .Times(1);
  3141. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  3142. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  3143. .Times(AtLeast(1));
  3144. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
  3145. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  3146. .Times(1);
  3147. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
  3148. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  3149. .Times(1);
  3150. }
  3151. std::vector<CrxUpdateItem> items;
  3152. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  3153. EXPECT_CALL(*receiver, Receive(_))
  3154. .WillRepeatedly(
  3155. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  3156. update_client->AddObserver(&observer);
  3157. const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
  3158. "ihfokbkgjpifnbbojhneepfflplebdkc"};
  3159. update_client->Update(
  3160. ids, base::BindOnce(&DataCallbackMock::Callback),
  3161. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  3162. false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  3163. RunThreads();
  3164. EXPECT_EQ(9u, items.size());
  3165. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  3166. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  3167. EXPECT_EQ(ComponentState::kChecking, items[1].state);
  3168. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[1].id.c_str());
  3169. EXPECT_EQ(ComponentState::kCanUpdate, items[2].state);
  3170. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str());
  3171. EXPECT_EQ(ComponentState::kUpdateError, items[3].state);
  3172. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str());
  3173. EXPECT_EQ(ComponentState::kCanUpdate, items[4].state);
  3174. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[4].id.c_str());
  3175. EXPECT_EQ(ComponentState::kDownloading, items[5].state);
  3176. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[5].id.c_str());
  3177. EXPECT_EQ(ComponentState::kDownloading, items[6].state);
  3178. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[6].id.c_str());
  3179. EXPECT_EQ(ComponentState::kUpdating, items[7].state);
  3180. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[7].id.c_str());
  3181. EXPECT_EQ(ComponentState::kUpdated, items[8].state);
  3182. EXPECT_STREQ("ihfokbkgjpifnbbojhneepfflplebdkc", items[8].id.c_str());
  3183. update_client->RemoveObserver(&observer);
  3184. }
  3185. // Tests the scenario where the update check fails.
  3186. TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) {
  3187. class DataCallbackMock {
  3188. public:
  3189. static std::vector<absl::optional<CrxComponent>> Callback(
  3190. const std::vector<std::string>& ids) {
  3191. CrxComponent crx;
  3192. crx.name = "test_jebg";
  3193. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  3194. crx.version = base::Version("0.9");
  3195. crx.installer = base::MakeRefCounted<TestInstaller>();
  3196. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  3197. return {crx};
  3198. }
  3199. };
  3200. class CompletionCallbackMock {
  3201. public:
  3202. static void Callback(base::OnceClosure quit_closure, Error error) {
  3203. EXPECT_EQ(Error::UPDATE_CHECK_ERROR, error);
  3204. std::move(quit_closure).Run();
  3205. }
  3206. };
  3207. class MockUpdateChecker : public UpdateChecker {
  3208. public:
  3209. static std::unique_ptr<UpdateChecker> Create(
  3210. scoped_refptr<Configurator> config,
  3211. PersistedData* metadata) {
  3212. return std::make_unique<MockUpdateChecker>();
  3213. }
  3214. void CheckForUpdates(
  3215. scoped_refptr<UpdateContext> context,
  3216. const base::flat_map<std::string, std::string>& additional_attributes,
  3217. UpdateCheckCallback update_check_callback) override {
  3218. EXPECT_FALSE(context->session_id.empty());
  3219. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  3220. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  3221. EXPECT_EQ(id, context->components_to_check_for_updates.front());
  3222. EXPECT_EQ(1u, context->components.count(id));
  3223. base::ThreadTaskRunnerHandle::Get()->PostTask(
  3224. FROM_HERE,
  3225. base::BindOnce(std::move(update_check_callback), absl::nullopt,
  3226. ErrorCategory::kUpdateCheck, -1, 0));
  3227. }
  3228. };
  3229. class MockCrxDownloader : public CrxDownloader {
  3230. public:
  3231. MockCrxDownloader() : CrxDownloader(nullptr) {}
  3232. private:
  3233. ~MockCrxDownloader() override = default;
  3234. void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
  3235. };
  3236. class MockPingManager : public MockPingManagerImpl {
  3237. public:
  3238. explicit MockPingManager(scoped_refptr<Configurator> config)
  3239. : MockPingManagerImpl(config) {}
  3240. protected:
  3241. ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
  3242. };
  3243. SetMockCrxDownloader<MockCrxDownloader>();
  3244. scoped_refptr<UpdateClient> update_client =
  3245. base::MakeRefCounted<UpdateClientImpl>(
  3246. config(), base::MakeRefCounted<MockPingManager>(config()),
  3247. &MockUpdateChecker::Create);
  3248. MockObserver observer;
  3249. {
  3250. InSequence seq;
  3251. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  3252. "jebgalgnebhfojomionfpkfelancnnkf"))
  3253. .Times(1);
  3254. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  3255. "jebgalgnebhfojomionfpkfelancnnkf"))
  3256. .Times(1)
  3257. .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
  3258. CrxUpdateItem item;
  3259. EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
  3260. EXPECT_EQ(ComponentState::kUpdateError, item.state);
  3261. EXPECT_EQ(5, static_cast<int>(item.error_category));
  3262. EXPECT_EQ(-1, item.error_code);
  3263. EXPECT_EQ(0, item.extra_code1);
  3264. }));
  3265. }
  3266. std::vector<CrxUpdateItem> items;
  3267. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  3268. EXPECT_CALL(*receiver, Receive(_))
  3269. .WillRepeatedly(
  3270. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  3271. update_client->AddObserver(&observer);
  3272. const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"};
  3273. update_client->Update(
  3274. ids, base::BindOnce(&DataCallbackMock::Callback),
  3275. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  3276. false, base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  3277. RunThreads();
  3278. EXPECT_EQ(2u, items.size());
  3279. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  3280. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  3281. EXPECT_EQ(ComponentState::kUpdateError, items[1].state);
  3282. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[1].id.c_str());
  3283. update_client->RemoveObserver(&observer);
  3284. }
  3285. // Tests the scenario where the server responds with different values for
  3286. // application status.
  3287. TEST_F(UpdateClientTest, OneCrxErrorUnknownApp) {
  3288. class DataCallbackMock {
  3289. public:
  3290. static std::vector<absl::optional<CrxComponent>> Callback(
  3291. const std::vector<std::string>& ids) {
  3292. std::vector<absl::optional<CrxComponent>> component;
  3293. {
  3294. CrxComponent crx;
  3295. crx.name = "test_jebg";
  3296. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  3297. crx.version = base::Version("0.9");
  3298. crx.installer = base::MakeRefCounted<TestInstaller>();
  3299. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  3300. component.push_back(crx);
  3301. }
  3302. {
  3303. CrxComponent crx;
  3304. crx.name = "test_abag";
  3305. crx.pk_hash.assign(abag_hash, abag_hash + std::size(abag_hash));
  3306. crx.version = base::Version("0.1");
  3307. crx.installer = base::MakeRefCounted<TestInstaller>();
  3308. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  3309. component.push_back(crx);
  3310. }
  3311. {
  3312. CrxComponent crx;
  3313. crx.name = "test_ihfo";
  3314. crx.pk_hash.assign(ihfo_hash, ihfo_hash + std::size(ihfo_hash));
  3315. crx.version = base::Version("0.2");
  3316. crx.installer = base::MakeRefCounted<TestInstaller>();
  3317. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  3318. component.push_back(crx);
  3319. }
  3320. {
  3321. CrxComponent crx;
  3322. crx.name = "test_gjpm";
  3323. crx.pk_hash.assign(gjpm_hash, gjpm_hash + std::size(gjpm_hash));
  3324. crx.version = base::Version("0.3");
  3325. crx.installer = base::MakeRefCounted<TestInstaller>();
  3326. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  3327. component.push_back(crx);
  3328. }
  3329. return component;
  3330. }
  3331. };
  3332. class CompletionCallbackMock {
  3333. public:
  3334. static void Callback(base::OnceClosure quit_closure, Error error) {
  3335. EXPECT_EQ(Error::NONE, error);
  3336. std::move(quit_closure).Run();
  3337. }
  3338. };
  3339. class MockUpdateChecker : public UpdateChecker {
  3340. public:
  3341. static std::unique_ptr<UpdateChecker> Create(
  3342. scoped_refptr<Configurator> config,
  3343. PersistedData* metadata) {
  3344. return std::make_unique<MockUpdateChecker>();
  3345. }
  3346. void CheckForUpdates(
  3347. scoped_refptr<UpdateContext> context,
  3348. const base::flat_map<std::string, std::string>& additional_attributes,
  3349. UpdateCheckCallback update_check_callback) override {
  3350. EXPECT_FALSE(context->session_id.empty());
  3351. EXPECT_EQ(4u, context->components_to_check_for_updates.size());
  3352. const std::string update_response =
  3353. ")]}'"
  3354. R"({"response": {)"
  3355. R"( "protocol": "3.1",)"
  3356. R"( "app": [)"
  3357. R"({"appid": "jebgalgnebhfojomionfpkfelancnnkf",)"
  3358. R"( "status": "error-unknownApplication"},)"
  3359. R"({"appid": "abagagagagagagagagagagagagagagag",)"
  3360. R"( "status": "restricted"},)"
  3361. R"({"appid": "ihfokbkgjpifnbbojhneepfflplebdkc",)"
  3362. R"( "status": "error-invalidAppId"},)"
  3363. R"({"appid": "gjpmebpgbhcamgdgjcmnjfhggjpgcimm",)"
  3364. R"( "status": "error-foobarApp"})"
  3365. R"(]}})";
  3366. const auto parser = ProtocolHandlerFactoryJSON().CreateParser();
  3367. EXPECT_TRUE(parser->Parse(update_response));
  3368. base::ThreadTaskRunnerHandle::Get()->PostTask(
  3369. FROM_HERE,
  3370. base::BindOnce(std::move(update_check_callback), parser->results(),
  3371. ErrorCategory::kNone, 0, 0));
  3372. }
  3373. };
  3374. class MockCrxDownloader : public CrxDownloader {
  3375. public:
  3376. MockCrxDownloader() : CrxDownloader(nullptr) {}
  3377. private:
  3378. ~MockCrxDownloader() override = default;
  3379. void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
  3380. };
  3381. class MockPingManager : public MockPingManagerImpl {
  3382. public:
  3383. explicit MockPingManager(scoped_refptr<Configurator> config)
  3384. : MockPingManagerImpl(config) {}
  3385. protected:
  3386. ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
  3387. };
  3388. SetMockCrxDownloader<MockCrxDownloader>();
  3389. scoped_refptr<UpdateClient> update_client =
  3390. base::MakeRefCounted<UpdateClientImpl>(
  3391. config(), base::MakeRefCounted<MockPingManager>(config()),
  3392. &MockUpdateChecker::Create);
  3393. MockObserver observer;
  3394. {
  3395. InSequence seq;
  3396. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  3397. "jebgalgnebhfojomionfpkfelancnnkf"))
  3398. .Times(1);
  3399. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  3400. "jebgalgnebhfojomionfpkfelancnnkf"))
  3401. .Times(1)
  3402. .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
  3403. CrxUpdateItem item;
  3404. EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
  3405. EXPECT_EQ(ComponentState::kUpdateError, item.state);
  3406. EXPECT_EQ(5, static_cast<int>(item.error_category));
  3407. EXPECT_EQ(-10006, item.error_code); // UNKNOWN_APPPLICATION.
  3408. EXPECT_EQ(0, item.extra_code1);
  3409. }));
  3410. }
  3411. {
  3412. InSequence seq;
  3413. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  3414. "abagagagagagagagagagagagagagagag"))
  3415. .Times(1);
  3416. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  3417. "abagagagagagagagagagagagagagagag"))
  3418. .Times(1)
  3419. .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
  3420. CrxUpdateItem item;
  3421. EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
  3422. EXPECT_EQ(ComponentState::kUpdateError, item.state);
  3423. EXPECT_EQ(5, static_cast<int>(item.error_category));
  3424. EXPECT_EQ(-10007, item.error_code); // RESTRICTED_APPLICATION.
  3425. EXPECT_EQ(0, item.extra_code1);
  3426. }));
  3427. }
  3428. {
  3429. InSequence seq;
  3430. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  3431. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  3432. .Times(1);
  3433. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  3434. "ihfokbkgjpifnbbojhneepfflplebdkc"))
  3435. .Times(1)
  3436. .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
  3437. CrxUpdateItem item;
  3438. EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
  3439. EXPECT_EQ(ComponentState::kUpdateError, item.state);
  3440. EXPECT_EQ(5, static_cast<int>(item.error_category));
  3441. EXPECT_EQ(-10008, item.error_code); // INVALID_APPID.
  3442. EXPECT_EQ(0, item.extra_code1);
  3443. }));
  3444. }
  3445. {
  3446. InSequence seq;
  3447. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  3448. "gjpmebpgbhcamgdgjcmnjfhggjpgcimm"))
  3449. .Times(1);
  3450. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  3451. "gjpmebpgbhcamgdgjcmnjfhggjpgcimm"))
  3452. .Times(1)
  3453. .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
  3454. CrxUpdateItem item;
  3455. EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
  3456. EXPECT_EQ(ComponentState::kUpdateError, item.state);
  3457. EXPECT_EQ(5, static_cast<int>(item.error_category));
  3458. EXPECT_EQ(-10004, item.error_code); // UPDATE_RESPONSE_NOT_FOUND.
  3459. EXPECT_EQ(0, item.extra_code1);
  3460. }));
  3461. }
  3462. update_client->AddObserver(&observer);
  3463. const std::vector<std::string> ids = {
  3464. "jebgalgnebhfojomionfpkfelancnnkf", "abagagagagagagagagagagagagagagag",
  3465. "ihfokbkgjpifnbbojhneepfflplebdkc", "gjpmebpgbhcamgdgjcmnjfhggjpgcimm"};
  3466. update_client->Update(
  3467. ids, base::BindOnce(&DataCallbackMock::Callback), {}, true,
  3468. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  3469. RunThreads();
  3470. update_client->RemoveObserver(&observer);
  3471. }
  3472. // Tests that a run action in invoked in the CRX install scenario.
  3473. TEST_F(UpdateClientTest, ActionRun_Install) {
  3474. class MockUpdateChecker : public UpdateChecker {
  3475. public:
  3476. static std::unique_ptr<UpdateChecker> Create(
  3477. scoped_refptr<Configurator> config,
  3478. PersistedData* metadata) {
  3479. return std::make_unique<MockUpdateChecker>();
  3480. }
  3481. void CheckForUpdates(
  3482. scoped_refptr<UpdateContext> context,
  3483. const base::flat_map<std::string, std::string>& additional_attributes,
  3484. UpdateCheckCallback update_check_callback) override {
  3485. /*
  3486. Mock the following response:
  3487. <?xml version='1.0' encoding='UTF-8'?>
  3488. <response protocol='3.1'>
  3489. <app appid='gjpmebpgbhcamgdgjcmnjfhggjpgcimm'>
  3490. <updatecheck status='ok'>
  3491. <urls>
  3492. <url codebase='http://localhost/download/'/>
  3493. </urls>
  3494. <manifest version='1.0' prodversionmin='11.0.1.0'>
  3495. <packages>
  3496. <package name='runaction_test_win.crx3'
  3497. hash_sha256='89290a0d2ff21ca5b45e109c6cc859ab5fe294e19c102d54acd321429c372cea'/>
  3498. </packages>
  3499. </manifest>
  3500. <actions>"
  3501. <action run='ChromeRecovery.crx3'/>"
  3502. </actions>"
  3503. </updatecheck>
  3504. </app>
  3505. </response>
  3506. */
  3507. EXPECT_FALSE(context->session_id.empty());
  3508. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  3509. const std::string id = "gjpmebpgbhcamgdgjcmnjfhggjpgcimm";
  3510. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  3511. EXPECT_EQ(1u, context->components.count(id));
  3512. ProtocolParser::Result::Manifest::Package package;
  3513. package.name = "runaction_test_win.crx3";
  3514. package.hash_sha256 =
  3515. "89290a0d2ff21ca5b45e109c6cc859ab5fe294e19c102d54acd321429c372cea";
  3516. ProtocolParser::Result result;
  3517. result.extension_id = id;
  3518. result.status = "ok";
  3519. result.crx_urls.push_back(GURL("http://localhost/download/"));
  3520. result.manifest.version = "1.0";
  3521. result.manifest.browser_min_version = "11.0.1.0";
  3522. result.manifest.packages.push_back(package);
  3523. result.action_run = "ChromeRecovery.crx3";
  3524. ProtocolParser::Results results;
  3525. results.list.push_back(result);
  3526. base::ThreadTaskRunnerHandle::Get()->PostTask(
  3527. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  3528. ErrorCategory::kNone, 0, 0));
  3529. }
  3530. };
  3531. class MockCrxDownloader : public CrxDownloader {
  3532. public:
  3533. MockCrxDownloader() : CrxDownloader(nullptr) {}
  3534. private:
  3535. ~MockCrxDownloader() override = default;
  3536. void DoStartDownload(const GURL& url) override {
  3537. DownloadMetrics download_metrics;
  3538. FilePath path;
  3539. Result result;
  3540. if (url.path() == "/download/runaction_test_win.crx3") {
  3541. download_metrics.url = url;
  3542. download_metrics.downloader = DownloadMetrics::kNone;
  3543. download_metrics.error = 0;
  3544. download_metrics.downloaded_bytes = 1843;
  3545. download_metrics.total_bytes = 1843;
  3546. download_metrics.download_time_ms = 1000;
  3547. EXPECT_TRUE(
  3548. MakeTestFile(TestFilePath("runaction_test_win.crx3"), &path));
  3549. result.error = 0;
  3550. result.response = path;
  3551. } else {
  3552. NOTREACHED();
  3553. }
  3554. base::ThreadTaskRunnerHandle::Get()->PostTask(
  3555. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  3556. base::Unretained(this), true, result,
  3557. download_metrics));
  3558. }
  3559. };
  3560. class MockPingManager : public MockPingManagerImpl {
  3561. public:
  3562. explicit MockPingManager(scoped_refptr<Configurator> config)
  3563. : MockPingManagerImpl(config) {}
  3564. protected:
  3565. ~MockPingManager() override {
  3566. EXPECT_EQ(3u, events().size());
  3567. /*
  3568. "<event eventtype="14" eventresult="1" downloader="unknown" "
  3569. "url="http://localhost/download/runaction_test_win.crx3"
  3570. "downloaded=1843 "
  3571. "total=1843 download_time_ms="1000" previousversion="0.0" "
  3572. "nextversion="1.0"/>"
  3573. */
  3574. const auto& event0 = events()[0];
  3575. EXPECT_EQ(14, event0.FindKey("eventtype")->GetInt());
  3576. EXPECT_EQ(1, event0.FindKey("eventresult")->GetInt());
  3577. EXPECT_EQ("unknown", event0.FindKey("downloader")->GetString());
  3578. EXPECT_EQ("http://localhost/download/runaction_test_win.crx3",
  3579. event0.FindKey("url")->GetString());
  3580. EXPECT_EQ(1843, event0.FindKey("downloaded")->GetDouble());
  3581. EXPECT_EQ(1843, event0.FindKey("total")->GetDouble());
  3582. EXPECT_EQ(1000, event0.FindKey("download_time_ms")->GetDouble());
  3583. EXPECT_EQ("0.0", event0.FindKey("previousversion")->GetString());
  3584. EXPECT_EQ("1.0", event0.FindKey("nextversion")->GetString());
  3585. // "<event eventtype="42" eventresult="1" errorcode="1877345072"/>"
  3586. const auto& event1 = events()[1];
  3587. EXPECT_EQ(42, event1.FindKey("eventtype")->GetInt());
  3588. EXPECT_EQ(1, event1.FindKey("eventresult")->GetInt());
  3589. EXPECT_EQ(1877345072, event1.FindKey("errorcode")->GetInt());
  3590. // "<event eventtype=\"2\" eventresult=\"1\" previousversion=\"0.0\" "
  3591. // "nextversion=\"1.0\"/>",
  3592. const auto& event2 = events()[2];
  3593. EXPECT_EQ(2, event2.FindKey("eventtype")->GetInt());
  3594. EXPECT_EQ(1, event1.FindKey("eventresult")->GetInt());
  3595. EXPECT_EQ("0.0", event0.FindKey("previousversion")->GetString());
  3596. EXPECT_EQ("1.0", event0.FindKey("nextversion")->GetString());
  3597. }
  3598. };
  3599. SetMockCrxDownloader<MockCrxDownloader>();
  3600. scoped_refptr<UpdateClient> update_client =
  3601. base::MakeRefCounted<UpdateClientImpl>(
  3602. config(), base::MakeRefCounted<MockPingManager>(config()),
  3603. &MockUpdateChecker::Create);
  3604. update_client->Install(
  3605. std::string("gjpmebpgbhcamgdgjcmnjfhggjpgcimm"),
  3606. base::BindOnce([](const std::vector<std::string>& ids) {
  3607. auto action_handler = base::MakeRefCounted<MockActionHandler>();
  3608. EXPECT_CALL(*action_handler, Handle(_, _, _))
  3609. .WillOnce([](const base::FilePath& action,
  3610. const std::string& session_id,
  3611. ActionHandler::Callback callback) {
  3612. EXPECT_EQ("ChromeRecovery.crx3",
  3613. action.BaseName().MaybeAsASCII());
  3614. EXPECT_TRUE(!session_id.empty());
  3615. std::move(callback).Run(true, 1877345072, 0);
  3616. });
  3617. CrxComponent crx;
  3618. crx.name = "test_niea";
  3619. crx.pk_hash.assign(gjpm_hash, gjpm_hash + std::size(gjpm_hash));
  3620. crx.version = base::Version("0.0");
  3621. crx.installer = base::MakeRefCounted<VersionedTestInstaller>();
  3622. crx.action_handler = action_handler;
  3623. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  3624. return std::vector<absl::optional<CrxComponent>>{crx};
  3625. }),
  3626. {},
  3627. base::BindOnce(
  3628. [](base::OnceClosure quit_closure, Error error) {
  3629. EXPECT_EQ(Error::NONE, error);
  3630. std::move(quit_closure).Run();
  3631. },
  3632. quit_closure()));
  3633. RunThreads();
  3634. }
  3635. // Tests that a run action is invoked in an update scenario when there was
  3636. // no update.
  3637. TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
  3638. class MockUpdateChecker : public UpdateChecker {
  3639. public:
  3640. static std::unique_ptr<UpdateChecker> Create(
  3641. scoped_refptr<Configurator> config,
  3642. PersistedData* metadata) {
  3643. return std::make_unique<MockUpdateChecker>();
  3644. }
  3645. void CheckForUpdates(
  3646. scoped_refptr<UpdateContext> context,
  3647. const base::flat_map<std::string, std::string>& additional_attributes,
  3648. UpdateCheckCallback update_check_callback) override {
  3649. /*
  3650. Mock the following response:
  3651. <?xml version='1.0' encoding='UTF-8'?>
  3652. <response protocol='3.1'>
  3653. <app appid='gjpmebpgbhcamgdgjcmnjfhggjpgcimm'>
  3654. <updatecheck status='noupdate'>
  3655. <actions>"
  3656. <action run=ChromeRecovery.crx3'/>"
  3657. </actions>"
  3658. </updatecheck>
  3659. </app>
  3660. </response>
  3661. */
  3662. EXPECT_FALSE(context->session_id.empty());
  3663. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  3664. const std::string id = "gjpmebpgbhcamgdgjcmnjfhggjpgcimm";
  3665. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  3666. EXPECT_EQ(1u, context->components.count(id));
  3667. ProtocolParser::Result result;
  3668. result.extension_id = id;
  3669. result.status = "noupdate";
  3670. result.action_run = "ChromeRecovery.crx3";
  3671. ProtocolParser::Results results;
  3672. results.list.push_back(result);
  3673. base::ThreadTaskRunnerHandle::Get()->PostTask(
  3674. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  3675. ErrorCategory::kNone, 0, 0));
  3676. }
  3677. };
  3678. class MockCrxDownloader : public CrxDownloader {
  3679. public:
  3680. MockCrxDownloader() : CrxDownloader(nullptr) {}
  3681. private:
  3682. ~MockCrxDownloader() override = default;
  3683. void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
  3684. };
  3685. class MockPingManager : public MockPingManagerImpl {
  3686. public:
  3687. explicit MockPingManager(scoped_refptr<Configurator> config)
  3688. : MockPingManagerImpl(config) {}
  3689. protected:
  3690. ~MockPingManager() override {
  3691. EXPECT_EQ(1u, events().size());
  3692. // "<event eventtype="42" eventresult="1" errorcode="1877345072"/>"
  3693. const auto& event = events()[0];
  3694. EXPECT_EQ(42, event.FindKey("eventtype")->GetInt());
  3695. EXPECT_EQ(1, event.FindKey("eventresult")->GetInt());
  3696. EXPECT_EQ(1877345072, event.FindKey("errorcode")->GetInt());
  3697. }
  3698. };
  3699. // Unpack the CRX to mock an existing install to be updated. The action to
  3700. // run is going to be resolved relative to this directory.
  3701. base::FilePath unpack_path;
  3702. {
  3703. base::RunLoop runloop;
  3704. base::OnceClosure quit_closure = runloop.QuitClosure();
  3705. auto config = base::MakeRefCounted<TestConfigurator>();
  3706. auto component_unpacker = base::MakeRefCounted<ComponentUnpacker>(
  3707. std::vector<uint8_t>(std::begin(gjpm_hash), std::end(gjpm_hash)),
  3708. TestFilePath("runaction_test_win.crx3"), nullptr,
  3709. config->GetUnzipperFactory()->Create(),
  3710. config->GetPatcherFactory()->Create(), crx_file::VerifierFormat::CRX3);
  3711. component_unpacker->Unpack(base::BindOnce(
  3712. [](base::FilePath* unpack_path, base::OnceClosure quit_closure,
  3713. const ComponentUnpacker::Result& result) {
  3714. EXPECT_EQ(UnpackerError::kNone, result.error);
  3715. EXPECT_EQ(0, result.extended_error);
  3716. *unpack_path = result.unpack_path;
  3717. std::move(quit_closure).Run();
  3718. },
  3719. &unpack_path, runloop.QuitClosure()));
  3720. runloop.Run();
  3721. }
  3722. EXPECT_FALSE(unpack_path.empty());
  3723. EXPECT_TRUE(base::DirectoryExists(unpack_path));
  3724. int64_t file_size = 0;
  3725. EXPECT_TRUE(base::GetFileSize(unpack_path.AppendASCII("ChromeRecovery.crx3"),
  3726. &file_size));
  3727. EXPECT_EQ(44582, file_size);
  3728. base::ScopedTempDir unpack_path_owner;
  3729. EXPECT_TRUE(unpack_path_owner.Set(unpack_path));
  3730. SetMockCrxDownloader<MockCrxDownloader>();
  3731. scoped_refptr<UpdateClient> update_client =
  3732. base::MakeRefCounted<UpdateClientImpl>(
  3733. config(), base::MakeRefCounted<MockPingManager>(config()),
  3734. &MockUpdateChecker::Create);
  3735. const std::vector<std::string> ids = {"gjpmebpgbhcamgdgjcmnjfhggjpgcimm"};
  3736. update_client->Update(
  3737. ids,
  3738. base::BindOnce(
  3739. [](const base::FilePath& unpack_path,
  3740. const std::vector<std::string>& ids) {
  3741. auto action_handler = base::MakeRefCounted<MockActionHandler>();
  3742. EXPECT_CALL(*action_handler, Handle(_, _, _))
  3743. .WillOnce([](const base::FilePath& action,
  3744. const std::string& session_id,
  3745. ActionHandler::Callback callback) {
  3746. EXPECT_EQ("ChromeRecovery.crx3",
  3747. action.BaseName().MaybeAsASCII());
  3748. EXPECT_TRUE(!session_id.empty());
  3749. std::move(callback).Run(true, 1877345072, 0);
  3750. });
  3751. CrxComponent crx;
  3752. crx.name = "test_niea";
  3753. crx.pk_hash.assign(gjpm_hash, gjpm_hash + std::size(gjpm_hash));
  3754. crx.version = base::Version("1.0");
  3755. crx.installer =
  3756. base::MakeRefCounted<ReadOnlyTestInstaller>(unpack_path);
  3757. crx.action_handler = action_handler;
  3758. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  3759. return std::vector<absl::optional<CrxComponent>>{crx};
  3760. },
  3761. unpack_path),
  3762. {}, false,
  3763. base::BindOnce(
  3764. [](base::OnceClosure quit_closure, Error error) {
  3765. EXPECT_EQ(Error::NONE, error);
  3766. std::move(quit_closure).Run();
  3767. },
  3768. quit_closure()));
  3769. RunThreads();
  3770. }
  3771. // Tests that custom response attributes are visible to observers.
  3772. TEST_F(UpdateClientTest, CustomAttributeNoUpdate) {
  3773. class DataCallbackMock {
  3774. public:
  3775. static std::vector<absl::optional<CrxComponent>> Callback(
  3776. const std::vector<std::string>& ids) {
  3777. CrxComponent crx;
  3778. crx.name = "test_jebg";
  3779. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  3780. crx.version = base::Version("0.9");
  3781. crx.installer = base::MakeRefCounted<TestInstaller>();
  3782. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  3783. std::vector<absl::optional<CrxComponent>> component = {crx};
  3784. return component;
  3785. }
  3786. };
  3787. class CompletionCallbackMock {
  3788. public:
  3789. static void Callback(base::OnceClosure quit_closure, Error error) {
  3790. EXPECT_EQ(Error::NONE, error);
  3791. std::move(quit_closure).Run();
  3792. }
  3793. };
  3794. class MockUpdateChecker : public UpdateChecker {
  3795. public:
  3796. static std::unique_ptr<UpdateChecker> Create(
  3797. scoped_refptr<Configurator> config,
  3798. PersistedData* metadata) {
  3799. return std::make_unique<MockUpdateChecker>();
  3800. }
  3801. void CheckForUpdates(
  3802. scoped_refptr<UpdateContext> context,
  3803. const base::flat_map<std::string, std::string>& additional_attributes,
  3804. UpdateCheckCallback update_check_callback) override {
  3805. EXPECT_FALSE(context->session_id.empty());
  3806. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  3807. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  3808. EXPECT_EQ(id, context->components_to_check_for_updates.front());
  3809. EXPECT_EQ(1u, context->components.count(id));
  3810. auto& component = context->components.at(id);
  3811. EXPECT_TRUE(component->is_foreground());
  3812. ProtocolParser::Result result;
  3813. result.extension_id = id;
  3814. result.status = "noupdate";
  3815. result.custom_attributes["_example"] = "example_value";
  3816. ProtocolParser::Results results;
  3817. results.list.push_back(result);
  3818. base::ThreadTaskRunnerHandle::Get()->PostTask(
  3819. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  3820. ErrorCategory::kNone, 0, 0));
  3821. }
  3822. };
  3823. class MockCrxDownloader : public CrxDownloader {
  3824. public:
  3825. MockCrxDownloader() : CrxDownloader(nullptr) {}
  3826. private:
  3827. ~MockCrxDownloader() override = default;
  3828. void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
  3829. };
  3830. class MockPingManager : public MockPingManagerImpl {
  3831. public:
  3832. explicit MockPingManager(scoped_refptr<Configurator> config)
  3833. : MockPingManagerImpl(config) {}
  3834. protected:
  3835. ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
  3836. };
  3837. SetMockCrxDownloader<MockCrxDownloader>();
  3838. scoped_refptr<UpdateClient> update_client =
  3839. base::MakeRefCounted<UpdateClientImpl>(
  3840. config(), base::MakeRefCounted<MockPingManager>(config()),
  3841. &MockUpdateChecker::Create);
  3842. class Observer : public UpdateClient::Observer {
  3843. public:
  3844. explicit Observer(scoped_refptr<UpdateClient> update_client)
  3845. : update_client_(update_client) {}
  3846. void OnEvent(Events event, const std::string& id) override {
  3847. if (event != Events::COMPONENT_ALREADY_UP_TO_DATE)
  3848. return;
  3849. ++calls;
  3850. CrxUpdateItem item;
  3851. EXPECT_TRUE(update_client_->GetCrxUpdateState(
  3852. "jebgalgnebhfojomionfpkfelancnnkf", &item));
  3853. EXPECT_EQ("example_value", item.custom_updatecheck_data["_example"]);
  3854. }
  3855. int calls = 0;
  3856. private:
  3857. scoped_refptr<UpdateClient> update_client_;
  3858. };
  3859. Observer observer(update_client);
  3860. update_client->AddObserver(&observer);
  3861. const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"};
  3862. update_client->Update(
  3863. ids, base::BindOnce(&DataCallbackMock::Callback), {}, true,
  3864. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  3865. RunThreads();
  3866. update_client->RemoveObserver(&observer);
  3867. EXPECT_EQ(1, observer.calls);
  3868. }
  3869. // Tests the scenario where `CrxDataCallback` returns a vector whose elements
  3870. // don't include a value for one of the component ids specified by the `ids`
  3871. // parameter of the `UpdateClient::Update` function. Expects the completion
  3872. // callback to include a specific error, and no other events and pings be
  3873. // generated, since the update engine rejects the UpdateClient::Update call.
  3874. TEST_F(UpdateClientTest, BadCrxDataCallback) {
  3875. class CompletionCallbackMock {
  3876. public:
  3877. static void Callback(base::OnceClosure quit_closure, Error error) {
  3878. EXPECT_EQ(Error::BAD_CRX_DATA_CALLBACK, error);
  3879. std::move(quit_closure).Run();
  3880. }
  3881. };
  3882. class MockPingManager : public MockPingManagerImpl {
  3883. public:
  3884. explicit MockPingManager(scoped_refptr<Configurator> config)
  3885. : MockPingManagerImpl(config) {}
  3886. protected:
  3887. ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
  3888. };
  3889. scoped_refptr<UpdateClient> update_client =
  3890. base::MakeRefCounted<UpdateClientImpl>(
  3891. config(), base::MakeRefCounted<MockPingManager>(config()),
  3892. UpdateChecker::Factory{});
  3893. MockObserver observer;
  3894. std::vector<CrxUpdateItem> items;
  3895. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  3896. EXPECT_CALL(*receiver, Receive(_))
  3897. .WillRepeatedly(
  3898. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  3899. update_client->AddObserver(&observer);
  3900. const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
  3901. "gjpmebpgbhcamgdgjcmnjfhggjpgcimm"};
  3902. // The `CrxDataCallback` argument only returns a value for the first
  3903. // component id. This means that its result is ill formed, and the `Update`
  3904. // call completes with an error.
  3905. update_client->Update(
  3906. ids, base::BindOnce([](const std::vector<std::string>& ids) {
  3907. EXPECT_EQ(ids.size(), size_t{2});
  3908. return std::vector<absl::optional<CrxComponent>>{absl::nullopt};
  3909. }),
  3910. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), true,
  3911. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  3912. RunThreads();
  3913. EXPECT_TRUE(items.empty());
  3914. update_client->RemoveObserver(&observer);
  3915. }
  3916. // Tests cancellation of an install before the task is run.
  3917. TEST_F(UpdateClientTest, CancelInstallBeforeTaskStart) {
  3918. class DataCallbackMock {
  3919. public:
  3920. static std::vector<absl::optional<CrxComponent>> Callback(
  3921. const std::vector<std::string>& ids) {
  3922. CrxComponent crx;
  3923. crx.name = "test_jebg";
  3924. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  3925. crx.version = base::Version("0.0");
  3926. crx.installer = base::MakeRefCounted<TestInstaller>();
  3927. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  3928. return {crx};
  3929. }
  3930. };
  3931. class CompletionCallbackMock {
  3932. public:
  3933. static void Callback(base::OnceClosure quit_closure, Error error) {
  3934. EXPECT_EQ(Error::UPDATE_CANCELED, error);
  3935. std::move(quit_closure).Run();
  3936. }
  3937. };
  3938. class MockUpdateChecker : public UpdateChecker {
  3939. public:
  3940. static std::unique_ptr<UpdateChecker> Create(
  3941. scoped_refptr<Configurator> config,
  3942. PersistedData* metadata) {
  3943. return std::make_unique<MockUpdateChecker>();
  3944. }
  3945. void CheckForUpdates(
  3946. scoped_refptr<UpdateContext> context,
  3947. const base::flat_map<std::string, std::string>& additional_attributes,
  3948. UpdateCheckCallback update_check_callback) override {
  3949. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  3950. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  3951. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  3952. EXPECT_EQ(1u, context->components.count(id));
  3953. ProtocolParser::Result::Manifest::Package package;
  3954. package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
  3955. package.hash_sha256 =
  3956. "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
  3957. package.fingerprint = "some-fingerprint";
  3958. ProtocolParser::Result result;
  3959. result.extension_id = id;
  3960. result.status = "ok";
  3961. result.crx_urls.emplace_back("http://localhost/download/");
  3962. result.manifest.version = "1.0";
  3963. result.manifest.browser_min_version = "11.0.1.0";
  3964. result.manifest.run = "UpdaterSetup.exe";
  3965. result.manifest.arguments = "--arg1 --arg2";
  3966. result.manifest.packages.push_back(package);
  3967. ProtocolParser::Results results;
  3968. results.list.push_back(result);
  3969. base::ThreadTaskRunnerHandle::Get()->PostTask(
  3970. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  3971. ErrorCategory::kNone, 0, 0));
  3972. }
  3973. };
  3974. class MockCrxDownloader : public CrxDownloader {
  3975. public:
  3976. MockCrxDownloader() : CrxDownloader(nullptr) {}
  3977. private:
  3978. ~MockCrxDownloader() override = default;
  3979. void DoStartDownload(const GURL& url) override {
  3980. DownloadMetrics download_metrics;
  3981. FilePath path;
  3982. Result result;
  3983. if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") {
  3984. download_metrics.url = url;
  3985. download_metrics.downloader = DownloadMetrics::kNone;
  3986. download_metrics.error = 0;
  3987. download_metrics.downloaded_bytes = 1843;
  3988. download_metrics.total_bytes = 1843;
  3989. download_metrics.download_time_ms = 1000;
  3990. EXPECT_TRUE(MakeTestFile(
  3991. TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
  3992. result.error = 0;
  3993. result.response = path;
  3994. } else {
  3995. NOTREACHED();
  3996. }
  3997. base::ThreadTaskRunnerHandle::Get()->PostTask(
  3998. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  3999. base::Unretained(this),
  4000. download_metrics.downloaded_bytes,
  4001. download_metrics.total_bytes));
  4002. base::ThreadTaskRunnerHandle::Get()->PostTask(
  4003. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  4004. base::Unretained(this), true, result,
  4005. download_metrics));
  4006. }
  4007. };
  4008. class MockPingManager : public MockPingManagerImpl {
  4009. public:
  4010. explicit MockPingManager(scoped_refptr<Configurator> config)
  4011. : MockPingManagerImpl(config) {}
  4012. protected:
  4013. ~MockPingManager() override {
  4014. const auto ping_data = MockPingManagerImpl::ping_data();
  4015. EXPECT_EQ(0u, ping_data.size());
  4016. }
  4017. };
  4018. SetMockCrxDownloader<MockCrxDownloader>();
  4019. scoped_refptr<UpdateClient> update_client =
  4020. base::MakeRefCounted<UpdateClientImpl>(
  4021. config(), base::MakeRefCounted<MockPingManager>(config()),
  4022. &MockUpdateChecker::Create);
  4023. std::vector<CrxUpdateItem> items;
  4024. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  4025. EXPECT_CALL(*receiver, Receive(_))
  4026. .WillRepeatedly(
  4027. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  4028. update_client
  4029. ->Install(
  4030. std::string("jebgalgnebhfojomionfpkfelancnnkf"),
  4031. base::BindOnce(&DataCallbackMock::Callback),
  4032. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  4033. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()))
  4034. .Run();
  4035. RunThreads();
  4036. EXPECT_EQ(0u, items.size());
  4037. }
  4038. // Tests cancellation of an install before the component installer runs.
  4039. TEST_F(UpdateClientTest, CancelInstallBeforeInstall) {
  4040. class DataCallbackMock {
  4041. public:
  4042. static std::vector<absl::optional<CrxComponent>> Callback(
  4043. const std::vector<std::string>& ids) {
  4044. CrxComponent crx;
  4045. crx.name = "test_jebg";
  4046. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  4047. crx.version = base::Version("0.0");
  4048. crx.installer = base::MakeRefCounted<TestInstaller>();
  4049. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  4050. return {crx};
  4051. }
  4052. };
  4053. class CompletionCallbackMock {
  4054. public:
  4055. static void Callback(base::OnceClosure quit_closure, Error error) {
  4056. EXPECT_EQ(Error::NONE, error);
  4057. std::move(quit_closure).Run();
  4058. }
  4059. };
  4060. class MockUpdateChecker : public UpdateChecker {
  4061. public:
  4062. static std::unique_ptr<UpdateChecker> Create(
  4063. scoped_refptr<Configurator> config,
  4064. PersistedData* metadata) {
  4065. return std::make_unique<MockUpdateChecker>();
  4066. }
  4067. void CheckForUpdates(
  4068. scoped_refptr<UpdateContext> context,
  4069. const base::flat_map<std::string, std::string>& additional_attributes,
  4070. UpdateCheckCallback update_check_callback) override {
  4071. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  4072. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  4073. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  4074. EXPECT_EQ(1u, context->components.count(id));
  4075. ProtocolParser::Result::Manifest::Package package;
  4076. package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
  4077. package.hash_sha256 =
  4078. "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
  4079. package.fingerprint = "some-fingerprint";
  4080. ProtocolParser::Result result;
  4081. result.extension_id = id;
  4082. result.status = "ok";
  4083. result.crx_urls.emplace_back("http://localhost/download/");
  4084. result.manifest.version = "1.0";
  4085. result.manifest.browser_min_version = "11.0.1.0";
  4086. result.manifest.run = "UpdaterSetup.exe";
  4087. result.manifest.arguments = "--arg1 --arg2";
  4088. result.manifest.packages.push_back(package);
  4089. ProtocolParser::Results results;
  4090. results.list.push_back(result);
  4091. base::ThreadTaskRunnerHandle::Get()->PostTask(
  4092. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  4093. ErrorCategory::kNone, 0, 0));
  4094. }
  4095. };
  4096. class MockCrxDownloader : public CrxDownloader {
  4097. public:
  4098. MockCrxDownloader() : CrxDownloader(nullptr) {}
  4099. private:
  4100. ~MockCrxDownloader() override = default;
  4101. void DoStartDownload(const GURL& url) override {
  4102. DownloadMetrics download_metrics;
  4103. FilePath path;
  4104. Result result;
  4105. if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") {
  4106. download_metrics.url = url;
  4107. download_metrics.downloader = DownloadMetrics::kNone;
  4108. download_metrics.error = 0;
  4109. download_metrics.downloaded_bytes = 1843;
  4110. download_metrics.total_bytes = 1843;
  4111. download_metrics.download_time_ms = 1000;
  4112. EXPECT_TRUE(MakeTestFile(
  4113. TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
  4114. result.error = 0;
  4115. result.response = path;
  4116. } else {
  4117. NOTREACHED();
  4118. }
  4119. base::ThreadTaskRunnerHandle::Get()->PostTask(
  4120. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  4121. base::Unretained(this),
  4122. download_metrics.downloaded_bytes,
  4123. download_metrics.total_bytes));
  4124. base::ThreadTaskRunnerHandle::Get()->PostTask(
  4125. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  4126. base::Unretained(this), true, result,
  4127. download_metrics));
  4128. }
  4129. };
  4130. class MockPingManager : public MockPingManagerImpl {
  4131. public:
  4132. explicit MockPingManager(scoped_refptr<Configurator> config)
  4133. : MockPingManagerImpl(config) {}
  4134. protected:
  4135. ~MockPingManager() override {
  4136. const auto ping_data = MockPingManagerImpl::ping_data();
  4137. EXPECT_EQ(1u, ping_data.size());
  4138. EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
  4139. EXPECT_EQ(base::Version("0.0"), ping_data[0].previous_version);
  4140. EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
  4141. EXPECT_EQ(ErrorCategory::kService, ping_data[0].error_category);
  4142. EXPECT_EQ(static_cast<int>(ServiceError::CANCELLED),
  4143. ping_data[0].error_code);
  4144. }
  4145. };
  4146. SetMockCrxDownloader<MockCrxDownloader>();
  4147. scoped_refptr<UpdateClient> update_client =
  4148. base::MakeRefCounted<UpdateClientImpl>(
  4149. config(), base::MakeRefCounted<MockPingManager>(config()),
  4150. &MockUpdateChecker::Create);
  4151. base::RepeatingClosure cancel;
  4152. MockObserver observer;
  4153. {
  4154. InSequence seq;
  4155. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  4156. "jebgalgnebhfojomionfpkfelancnnkf"))
  4157. .Times(1);
  4158. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  4159. "jebgalgnebhfojomionfpkfelancnnkf"))
  4160. .Times(1);
  4161. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
  4162. "jebgalgnebhfojomionfpkfelancnnkf"))
  4163. .Times(AtLeast(1))
  4164. .WillRepeatedly(Invoke([&cancel]() { cancel.Run(); }));
  4165. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  4166. "jebgalgnebhfojomionfpkfelancnnkf"))
  4167. .Times(1);
  4168. }
  4169. std::vector<CrxUpdateItem> items;
  4170. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  4171. EXPECT_CALL(*receiver, Receive(_))
  4172. .WillRepeatedly(
  4173. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  4174. update_client->AddObserver(&observer);
  4175. cancel = update_client->Install(
  4176. std::string("jebgalgnebhfojomionfpkfelancnnkf"),
  4177. base::BindOnce(&DataCallbackMock::Callback),
  4178. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  4179. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  4180. RunThreads();
  4181. EXPECT_EQ(5u, items.size());
  4182. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  4183. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  4184. EXPECT_EQ(ComponentState::kCanUpdate, items[1].state);
  4185. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[1].id.c_str());
  4186. EXPECT_EQ(ComponentState::kDownloading, items[2].state);
  4187. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str());
  4188. EXPECT_EQ(ComponentState::kDownloading, items[3].state);
  4189. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[3].id.c_str());
  4190. EXPECT_EQ(ComponentState::kUpdateError, items[4].state);
  4191. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[4].id.c_str());
  4192. update_client->RemoveObserver(&observer);
  4193. }
  4194. // Tests cancellation of an install before the download.
  4195. TEST_F(UpdateClientTest, CancelInstallBeforeDownload) {
  4196. class DataCallbackMock {
  4197. public:
  4198. static std::vector<absl::optional<CrxComponent>> Callback(
  4199. const std::vector<std::string>& ids) {
  4200. CrxComponent crx;
  4201. crx.name = "test_jebg";
  4202. crx.pk_hash.assign(jebg_hash, jebg_hash + std::size(jebg_hash));
  4203. crx.version = base::Version("0.0");
  4204. crx.installer = base::MakeRefCounted<TestInstaller>();
  4205. crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
  4206. return {crx};
  4207. }
  4208. };
  4209. class CompletionCallbackMock {
  4210. public:
  4211. static void Callback(base::OnceClosure quit_closure, Error error) {
  4212. EXPECT_EQ(Error::NONE, error);
  4213. std::move(quit_closure).Run();
  4214. }
  4215. };
  4216. class MockUpdateChecker : public UpdateChecker {
  4217. public:
  4218. static std::unique_ptr<UpdateChecker> Create(
  4219. scoped_refptr<Configurator> config,
  4220. PersistedData* metadata) {
  4221. return std::make_unique<MockUpdateChecker>();
  4222. }
  4223. void CheckForUpdates(
  4224. scoped_refptr<UpdateContext> context,
  4225. const base::flat_map<std::string, std::string>& additional_attributes,
  4226. UpdateCheckCallback update_check_callback) override {
  4227. EXPECT_EQ(1u, context->components_to_check_for_updates.size());
  4228. const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
  4229. EXPECT_EQ(id, context->components_to_check_for_updates[0]);
  4230. EXPECT_EQ(1u, context->components.count(id));
  4231. ProtocolParser::Result::Manifest::Package package;
  4232. package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
  4233. package.hash_sha256 =
  4234. "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
  4235. package.fingerprint = "some-fingerprint";
  4236. ProtocolParser::Result result;
  4237. result.extension_id = id;
  4238. result.status = "ok";
  4239. result.crx_urls.emplace_back("http://localhost/download/");
  4240. result.manifest.version = "1.0";
  4241. result.manifest.browser_min_version = "11.0.1.0";
  4242. result.manifest.run = "UpdaterSetup.exe";
  4243. result.manifest.arguments = "--arg1 --arg2";
  4244. result.manifest.packages.push_back(package);
  4245. ProtocolParser::Results results;
  4246. results.list.push_back(result);
  4247. base::ThreadTaskRunnerHandle::Get()->PostTask(
  4248. FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
  4249. ErrorCategory::kNone, 0, 0));
  4250. }
  4251. };
  4252. class MockCrxDownloader : public CrxDownloader {
  4253. public:
  4254. MockCrxDownloader() : CrxDownloader(nullptr) {}
  4255. private:
  4256. ~MockCrxDownloader() override = default;
  4257. void DoStartDownload(const GURL& url) override {
  4258. DownloadMetrics download_metrics;
  4259. FilePath path;
  4260. Result result;
  4261. if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") {
  4262. download_metrics.url = url;
  4263. download_metrics.downloader = DownloadMetrics::kNone;
  4264. download_metrics.error = 0;
  4265. download_metrics.downloaded_bytes = 1843;
  4266. download_metrics.total_bytes = 1843;
  4267. download_metrics.download_time_ms = 1000;
  4268. EXPECT_TRUE(MakeTestFile(
  4269. TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
  4270. result.error = 0;
  4271. result.response = path;
  4272. } else {
  4273. NOTREACHED();
  4274. }
  4275. base::ThreadTaskRunnerHandle::Get()->PostTask(
  4276. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
  4277. base::Unretained(this),
  4278. download_metrics.downloaded_bytes,
  4279. download_metrics.total_bytes));
  4280. base::ThreadTaskRunnerHandle::Get()->PostTask(
  4281. FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
  4282. base::Unretained(this), true, result,
  4283. download_metrics));
  4284. }
  4285. };
  4286. class MockPingManager : public MockPingManagerImpl {
  4287. public:
  4288. explicit MockPingManager(scoped_refptr<Configurator> config)
  4289. : MockPingManagerImpl(config) {}
  4290. protected:
  4291. ~MockPingManager() override {
  4292. const auto ping_data = MockPingManagerImpl::ping_data();
  4293. EXPECT_EQ(1u, ping_data.size());
  4294. EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
  4295. EXPECT_EQ(base::Version("0.0"), ping_data[0].previous_version);
  4296. EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
  4297. EXPECT_EQ(ErrorCategory::kService, ping_data[0].error_category);
  4298. EXPECT_EQ(static_cast<int>(ServiceError::CANCELLED),
  4299. ping_data[0].error_code);
  4300. }
  4301. };
  4302. SetMockCrxDownloader<MockCrxDownloader>();
  4303. scoped_refptr<UpdateClient> update_client =
  4304. base::MakeRefCounted<UpdateClientImpl>(
  4305. config(), base::MakeRefCounted<MockPingManager>(config()),
  4306. &MockUpdateChecker::Create);
  4307. base::RepeatingClosure cancel;
  4308. MockObserver observer;
  4309. {
  4310. InSequence seq;
  4311. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
  4312. "jebgalgnebhfojomionfpkfelancnnkf"))
  4313. .Times(1);
  4314. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
  4315. "jebgalgnebhfojomionfpkfelancnnkf"))
  4316. .Times(1)
  4317. .WillOnce(Invoke([&cancel]() { cancel.Run(); }));
  4318. EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
  4319. "jebgalgnebhfojomionfpkfelancnnkf"))
  4320. .Times(1);
  4321. }
  4322. std::vector<CrxUpdateItem> items;
  4323. auto receiver = base::MakeRefCounted<MockCrxStateChangeReceiver>();
  4324. EXPECT_CALL(*receiver, Receive(_))
  4325. .WillRepeatedly(
  4326. [&items](const CrxUpdateItem& item) { items.push_back(item); });
  4327. update_client->AddObserver(&observer);
  4328. cancel = update_client->Install(
  4329. std::string("jebgalgnebhfojomionfpkfelancnnkf"),
  4330. base::BindOnce(&DataCallbackMock::Callback),
  4331. base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver),
  4332. base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
  4333. RunThreads();
  4334. EXPECT_EQ(3u, items.size());
  4335. EXPECT_EQ(ComponentState::kChecking, items[0].state);
  4336. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[0].id.c_str());
  4337. EXPECT_EQ(ComponentState::kCanUpdate, items[1].state);
  4338. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[1].id.c_str());
  4339. EXPECT_EQ(ComponentState::kUpdateError, items[2].state);
  4340. EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", items[2].id.c_str());
  4341. update_client->RemoveObserver(&observer);
  4342. }
  4343. } // namespace update_client