nsDocShell.cpp 462 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "nsDocShell.h"
  6. #include <algorithm>
  7. #include "mozilla/ArrayUtils.h"
  8. #include "mozilla/Attributes.h"
  9. #include "mozilla/AutoRestore.h"
  10. #include "mozilla/BasePrincipal.h"
  11. #include "mozilla/Casting.h"
  12. #include "mozilla/dom/ContentChild.h"
  13. #include "mozilla/dom/ChromeUtils.h"
  14. #include "mozilla/dom/Element.h"
  15. #include "mozilla/dom/TabChild.h"
  16. #include "mozilla/dom/ProfileTimelineMarkerBinding.h"
  17. #include "mozilla/dom/ScreenOrientation.h"
  18. #include "mozilla/dom/ToJSValue.h"
  19. #include "mozilla/dom/PermissionMessageUtils.h"
  20. #include "mozilla/dom/workers/ServiceWorkerManager.h"
  21. #include "mozilla/EventStateManager.h"
  22. #include "mozilla/LoadInfo.h"
  23. #include "mozilla/Preferences.h"
  24. #include "mozilla/Services.h"
  25. #include "mozilla/StartupTimeline.h"
  26. #include "mozilla/Unused.h"
  27. #include "Navigator.h"
  28. #include "URIUtils.h"
  29. #include "mozilla/dom/DocGroup.h"
  30. #include "mozilla/dom/TabGroup.h"
  31. #include "nsIContent.h"
  32. #include "nsIContentInlines.h"
  33. #include "nsIDocument.h"
  34. #include "nsIDOMDocument.h"
  35. #include "nsIDOMElement.h"
  36. #include "nsAboutProtocolUtils.h"
  37. #include "nsArray.h"
  38. #include "nsArrayUtils.h"
  39. #include "nsContentSecurityManager.h"
  40. #include "nsICaptivePortalService.h"
  41. #include "nsIDOMStorage.h"
  42. #include "nsIContentViewer.h"
  43. #include "nsIDocumentLoaderFactory.h"
  44. #include "nsCURILoader.h"
  45. #include "nsDocShellCID.h"
  46. #include "nsDOMCID.h"
  47. #include "nsNetCID.h"
  48. #include "nsNetUtil.h"
  49. #include "mozilla/net/ReferrerPolicy.h"
  50. #include "nsRect.h"
  51. #include "prenv.h"
  52. #include "nsIDOMWindow.h"
  53. #include "nsIGlobalObject.h"
  54. #include "nsIViewSourceChannel.h"
  55. #include "nsIWebBrowserChrome.h"
  56. #include "nsPoint.h"
  57. #include "nsIObserverService.h"
  58. #include "nsIPrompt.h"
  59. #include "nsIAuthPrompt.h"
  60. #include "nsIAuthPrompt2.h"
  61. #include "nsIChannelEventSink.h"
  62. #include "nsIAsyncVerifyRedirectCallback.h"
  63. #include "nsIScriptSecurityManager.h"
  64. #include "nsIScriptObjectPrincipal.h"
  65. #include "nsIScrollableFrame.h"
  66. #include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
  67. #include "nsISeekableStream.h"
  68. #include "nsAutoPtr.h"
  69. #include "nsQueryObject.h"
  70. #include "nsIWritablePropertyBag2.h"
  71. #include "nsIAppShell.h"
  72. #include "nsWidgetsCID.h"
  73. #include "nsIInterfaceRequestorUtils.h"
  74. #include "nsView.h"
  75. #include "nsViewManager.h"
  76. #include "nsIScriptChannel.h"
  77. #include "nsITimedChannel.h"
  78. #include "nsIPrivacyTransitionObserver.h"
  79. #include "nsIReflowObserver.h"
  80. #include "nsIScrollObserver.h"
  81. #include "nsIDocShellTreeItem.h"
  82. #include "nsIChannel.h"
  83. #include "IHistory.h"
  84. #include "nsViewSourceHandler.h"
  85. #include "nsWhitespaceTokenizer.h"
  86. #include "nsICookieService.h"
  87. #include "nsIConsoleReportCollector.h"
  88. #include "nsObjectLoadingContent.h"
  89. // we want to explore making the document own the load group
  90. // so we can associate the document URI with the load group.
  91. // until this point, we have an evil hack:
  92. #include "nsIHttpChannelInternal.h"
  93. #include "nsPILoadGroupInternal.h"
  94. // Local Includes
  95. #include "nsDocShellLoadInfo.h"
  96. #include "nsCDefaultURIFixup.h"
  97. #include "nsDocShellEnumerator.h"
  98. #include "nsSHistory.h"
  99. #include "nsDocShellEditorData.h"
  100. #include "GeckoProfiler.h"
  101. #include "timeline/JavascriptTimelineMarker.h"
  102. // Helper Classes
  103. #include "nsError.h"
  104. #include "nsEscape.h"
  105. // Interfaces Needed
  106. #include "nsIFormPOSTActionChannel.h"
  107. #include "nsIUploadChannel.h"
  108. #include "nsIUploadChannel2.h"
  109. #include "nsIWebProgress.h"
  110. #include "nsILayoutHistoryState.h"
  111. #include "nsITimer.h"
  112. #include "nsISHistoryInternal.h"
  113. #include "nsIPrincipal.h"
  114. #include "nsNullPrincipal.h"
  115. #include "nsISHEntry.h"
  116. #include "nsIWindowWatcher.h"
  117. #include "nsIPromptFactory.h"
  118. #include "nsITransportSecurityInfo.h"
  119. #include "nsINode.h"
  120. #include "nsINSSErrorsService.h"
  121. #include "nsIApplicationCacheChannel.h"
  122. #include "nsIApplicationCacheContainer.h"
  123. #include "nsStreamUtils.h"
  124. #include "nsIController.h"
  125. #include "nsPICommandUpdater.h"
  126. #include "nsIDOMHTMLAnchorElement.h"
  127. #include "nsIWebBrowserChrome3.h"
  128. #include "nsITabChild.h"
  129. #include "nsISiteSecurityService.h"
  130. #include "nsStructuredCloneContainer.h"
  131. #include "nsIStructuredCloneContainer.h"
  132. #include "nsISupportsPrimitives.h"
  133. #ifdef MOZ_PLACES
  134. #include "nsIFaviconService.h"
  135. #include "mozIPlacesPendingOperation.h"
  136. #include "mozIAsyncFavicons.h"
  137. #endif
  138. #include "nsINetworkPredictor.h"
  139. // Editor-related
  140. #include "nsIEditingSession.h"
  141. #include "nsPIDOMWindow.h"
  142. #include "nsGlobalWindow.h"
  143. #include "nsPIWindowRoot.h"
  144. #include "nsICachingChannel.h"
  145. #include "nsIMultiPartChannel.h"
  146. #include "nsIWyciwygChannel.h"
  147. // For reporting errors with the console service.
  148. // These can go away if error reporting is propagated up past nsDocShell.
  149. #include "nsIScriptError.h"
  150. // used to dispatch urls to default protocol handlers
  151. #include "nsCExternalHandlerService.h"
  152. #include "nsIExternalProtocolService.h"
  153. #include "nsFocusManager.h"
  154. #include "nsITextToSubURI.h"
  155. #include "nsIJARChannel.h"
  156. #include "mozilla/Logging.h"
  157. #include "nsISelectionDisplay.h"
  158. #include "nsIGlobalHistory2.h"
  159. #include "nsIFrame.h"
  160. #include "nsSubDocumentFrame.h"
  161. // for embedding
  162. #include "nsIWebBrowserChromeFocus.h"
  163. #if NS_PRINT_PREVIEW
  164. #include "nsIDocumentViewerPrint.h"
  165. #include "nsIWebBrowserPrint.h"
  166. #endif
  167. #include "nsContentUtils.h"
  168. #include "nsIContentSecurityPolicy.h"
  169. #include "nsILoadInfo.h"
  170. #include "nsSandboxFlags.h"
  171. #include "nsXULAppAPI.h"
  172. #include "nsDOMNavigationTiming.h"
  173. #include "nsIAppsService.h"
  174. #include "nsDSURIContentListener.h"
  175. #include "nsDocShellLoadTypes.h"
  176. #include "nsDocShellTransferableHooks.h"
  177. #include "nsICommandManager.h"
  178. #include "nsIDOMNode.h"
  179. #include "nsIDocShellTreeOwner.h"
  180. #include "nsIHttpChannel.h"
  181. #include "nsIIDNService.h"
  182. #include "nsIInputStreamChannel.h"
  183. #include "nsINestedURI.h"
  184. #include "nsISHContainer.h"
  185. #include "nsISHistory.h"
  186. #include "nsISecureBrowserUI.h"
  187. #include "nsISocketProvider.h"
  188. #include "nsIStringBundle.h"
  189. #include "nsIURIFixup.h"
  190. #include "nsIURILoader.h"
  191. #include "nsIURL.h"
  192. #include "nsIWebBrowserFind.h"
  193. #include "nsIWidget.h"
  194. #include "mozilla/dom/EncodingUtils.h"
  195. #include "mozilla/dom/PerformanceNavigation.h"
  196. #include "mozilla/dom/ScriptSettings.h"
  197. #ifdef MOZ_TOOLKIT_SEARCH
  198. #include "nsIBrowserSearchService.h"
  199. #endif
  200. #include "mozIThirdPartyUtil.h"
  201. static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
  202. #if defined(DEBUG_bryner) || defined(DEBUG_chb)
  203. //#define DEBUG_DOCSHELL_FOCUS
  204. #define DEBUG_PAGE_CACHE
  205. #endif
  206. #ifdef XP_WIN
  207. #include <process.h>
  208. #define getpid _getpid
  209. #else
  210. #include <unistd.h> // for getpid()
  211. #endif
  212. using namespace mozilla;
  213. using namespace mozilla::dom;
  214. using mozilla::dom::workers::ServiceWorkerManager;
  215. // True means sUseErrorPages has been added to
  216. // preferences var cache.
  217. static bool gAddedPreferencesVarCache = false;
  218. bool nsDocShell::sUseErrorPages = false;
  219. // Number of documents currently loading
  220. static int32_t gNumberOfDocumentsLoading = 0;
  221. // Global count of existing docshells.
  222. static int32_t gDocShellCount = 0;
  223. // Global count of docshells with the private attribute set
  224. static uint32_t gNumberOfPrivateDocShells = 0;
  225. // Global reference to the URI fixup service.
  226. nsIURIFixup* nsDocShell::sURIFixup = 0;
  227. // True means we validate window targets to prevent frameset
  228. // spoofing. Initialize this to a non-bolean value so we know to check
  229. // the pref on the creation of the first docshell.
  230. static uint32_t gValidateOrigin = 0xffffffff;
  231. // Hint for native dispatch of events on how long to delay after
  232. // all documents have loaded in milliseconds before favoring normal
  233. // native event dispatch priorites over performance
  234. // Can be overridden with docshell.event_starvation_delay_hint pref.
  235. #define NS_EVENT_STARVATION_DELAY_HINT 2000
  236. #ifdef DEBUG
  237. static mozilla::LazyLogModule gDocShellLog("nsDocShell");
  238. #endif
  239. static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");;
  240. const char kBrandBundleURL[] = "chrome://branding/locale/brand.properties";
  241. const char kAppstringsBundleURL[] = "chrome://global/locale/appstrings.properties";
  242. static void
  243. FavorPerformanceHint(bool aPerfOverStarvation)
  244. {
  245. nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
  246. if (appShell) {
  247. appShell->FavorPerformanceHint(
  248. aPerfOverStarvation,
  249. Preferences::GetUint("docshell.event_starvation_delay_hint",
  250. NS_EVENT_STARVATION_DELAY_HINT));
  251. }
  252. }
  253. //*****************************************************************************
  254. // <a ping> support
  255. //*****************************************************************************
  256. #define PREF_PINGS_ENABLED "browser.send_pings"
  257. #define PREF_PINGS_MAX_PER_LINK "browser.send_pings.max_per_link"
  258. #define PREF_PINGS_REQUIRE_SAME_HOST "browser.send_pings.require_same_host"
  259. // Check prefs to see if pings are enabled and if so what restrictions might
  260. // be applied.
  261. //
  262. // @param maxPerLink
  263. // This parameter returns the number of pings that are allowed per link click
  264. //
  265. // @param requireSameHost
  266. // This parameter returns true if pings are restricted to the same host as
  267. // the document in which the click occurs. If the same host restriction is
  268. // imposed, then we still allow for pings to cross over to different
  269. // protocols and ports for flexibility and because it is not possible to send
  270. // a ping via FTP.
  271. //
  272. // @returns
  273. // true if pings are enabled and false otherwise.
  274. //
  275. static bool
  276. PingsEnabled(int32_t* aMaxPerLink, bool* aRequireSameHost)
  277. {
  278. bool allow = Preferences::GetBool(PREF_PINGS_ENABLED, false);
  279. *aMaxPerLink = 1;
  280. *aRequireSameHost = true;
  281. if (allow) {
  282. Preferences::GetInt(PREF_PINGS_MAX_PER_LINK, aMaxPerLink);
  283. Preferences::GetBool(PREF_PINGS_REQUIRE_SAME_HOST, aRequireSameHost);
  284. }
  285. return allow;
  286. }
  287. typedef void (*ForEachPingCallback)(void* closure, nsIContent* content,
  288. nsIURI* uri, nsIIOService* ios);
  289. static bool
  290. IsElementAnchor(nsIContent* aContent)
  291. {
  292. // Make sure we are dealing with either an <A> or <AREA> element in the HTML
  293. // or XHTML namespace.
  294. return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area);
  295. }
  296. static void
  297. ForEachPing(nsIContent* aContent, ForEachPingCallback aCallback, void* aClosure)
  298. {
  299. // NOTE: Using nsIDOMHTMLAnchorElement::GetPing isn't really worth it here
  300. // since we'd still need to parse the resulting string. Instead, we
  301. // just parse the raw attribute. It might be nice if the content node
  302. // implemented an interface that exposed an enumeration of nsIURIs.
  303. // Make sure we are dealing with either an <A> or <AREA> element in the HTML
  304. // or XHTML namespace.
  305. if (!IsElementAnchor(aContent)) {
  306. return;
  307. }
  308. nsCOMPtr<nsIAtom> pingAtom = NS_Atomize("ping");
  309. if (!pingAtom) {
  310. return;
  311. }
  312. nsAutoString value;
  313. aContent->GetAttr(kNameSpaceID_None, pingAtom, value);
  314. if (value.IsEmpty()) {
  315. return;
  316. }
  317. nsCOMPtr<nsIIOService> ios = do_GetIOService();
  318. if (!ios) {
  319. return;
  320. }
  321. nsIDocument* doc = aContent->OwnerDoc();
  322. nsWhitespaceTokenizer tokenizer(value);
  323. while (tokenizer.hasMoreTokens()) {
  324. nsCOMPtr<nsIURI> uri, baseURI = aContent->GetBaseURI();
  325. ios->NewURI(NS_ConvertUTF16toUTF8(tokenizer.nextToken()),
  326. doc->GetDocumentCharacterSet().get(),
  327. baseURI, getter_AddRefs(uri));
  328. // if we can't generate a valid URI, then there is nothing to do
  329. if (!uri) {
  330. continue;
  331. }
  332. // Explicitly not allow loading data: URIs
  333. bool isDataScheme =
  334. (NS_SUCCEEDED(uri->SchemeIs("data", &isDataScheme)) && isDataScheme);
  335. if (!isDataScheme) {
  336. aCallback(aClosure, aContent, uri, ios);
  337. }
  338. }
  339. }
  340. //----------------------------------------------------------------------
  341. // We wait this many milliseconds before killing the ping channel...
  342. #define PING_TIMEOUT 10000
  343. static void
  344. OnPingTimeout(nsITimer* aTimer, void* aClosure)
  345. {
  346. nsILoadGroup* loadGroup = static_cast<nsILoadGroup*>(aClosure);
  347. if (loadGroup) {
  348. loadGroup->Cancel(NS_ERROR_ABORT);
  349. }
  350. }
  351. class nsPingListener final
  352. : public nsIStreamListener
  353. {
  354. public:
  355. NS_DECL_ISUPPORTS
  356. NS_DECL_NSIREQUESTOBSERVER
  357. NS_DECL_NSISTREAMLISTENER
  358. nsPingListener()
  359. {
  360. }
  361. void SetLoadGroup(nsILoadGroup* aLoadGroup) {
  362. mLoadGroup = aLoadGroup;
  363. }
  364. nsresult StartTimeout();
  365. private:
  366. ~nsPingListener();
  367. nsCOMPtr<nsILoadGroup> mLoadGroup;
  368. nsCOMPtr<nsITimer> mTimer;
  369. };
  370. NS_IMPL_ISUPPORTS(nsPingListener, nsIStreamListener, nsIRequestObserver)
  371. nsPingListener::~nsPingListener()
  372. {
  373. if (mTimer) {
  374. mTimer->Cancel();
  375. mTimer = nullptr;
  376. }
  377. }
  378. nsresult
  379. nsPingListener::StartTimeout()
  380. {
  381. nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
  382. if (timer) {
  383. nsresult rv = timer->InitWithFuncCallback(OnPingTimeout, mLoadGroup,
  384. PING_TIMEOUT,
  385. nsITimer::TYPE_ONE_SHOT);
  386. if (NS_SUCCEEDED(rv)) {
  387. mTimer = timer;
  388. return NS_OK;
  389. }
  390. }
  391. return NS_ERROR_OUT_OF_MEMORY;
  392. }
  393. NS_IMETHODIMP
  394. nsPingListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
  395. {
  396. return NS_OK;
  397. }
  398. NS_IMETHODIMP
  399. nsPingListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
  400. nsIInputStream* aStream, uint64_t aOffset,
  401. uint32_t aCount)
  402. {
  403. uint32_t result;
  404. return aStream->ReadSegments(NS_DiscardSegment, nullptr, aCount, &result);
  405. }
  406. NS_IMETHODIMP
  407. nsPingListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
  408. nsresult aStatus)
  409. {
  410. mLoadGroup = nullptr;
  411. if (mTimer) {
  412. mTimer->Cancel();
  413. mTimer = nullptr;
  414. }
  415. return NS_OK;
  416. }
  417. struct MOZ_STACK_CLASS SendPingInfo
  418. {
  419. int32_t numPings;
  420. int32_t maxPings;
  421. bool requireSameHost;
  422. nsIURI* target;
  423. nsIURI* referrer;
  424. nsIDocShell* docShell;
  425. uint32_t referrerPolicy;
  426. };
  427. static void
  428. SendPing(void* aClosure, nsIContent* aContent, nsIURI* aURI,
  429. nsIIOService* aIOService)
  430. {
  431. SendPingInfo* info = static_cast<SendPingInfo*>(aClosure);
  432. if (info->maxPings > -1 && info->numPings >= info->maxPings) {
  433. return;
  434. }
  435. nsIDocument* doc = aContent->OwnerDoc();
  436. nsCOMPtr<nsIChannel> chan;
  437. NS_NewChannel(getter_AddRefs(chan),
  438. aURI,
  439. doc,
  440. info->requireSameHost
  441. ? nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED
  442. : nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
  443. nsIContentPolicy::TYPE_PING,
  444. nullptr, // aLoadGroup
  445. nullptr, // aCallbacks
  446. nsIRequest::LOAD_NORMAL, // aLoadFlags,
  447. aIOService);
  448. if (!chan) {
  449. return;
  450. }
  451. // Don't bother caching the result of this URI load, but do not exempt
  452. // it from Safe Browsing.
  453. chan->SetLoadFlags(nsIRequest::INHIBIT_CACHING | nsIChannel::LOAD_CLASSIFY_URI);
  454. nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(chan);
  455. if (!httpChan) {
  456. return;
  457. }
  458. // This is needed in order for 3rd-party cookie blocking to work.
  459. nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(httpChan);
  460. if (httpInternal) {
  461. httpInternal->SetDocumentURI(doc->GetDocumentURI());
  462. }
  463. httpChan->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
  464. // Remove extraneous request headers (to reduce request size)
  465. httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept"),
  466. EmptyCString(), false);
  467. httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-language"),
  468. EmptyCString(), false);
  469. httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-encoding"),
  470. EmptyCString(), false);
  471. // Always send a Ping-To header.
  472. nsAutoCString pingTo;
  473. if (NS_SUCCEEDED(info->target->GetSpec(pingTo))) {
  474. httpChan->SetRequestHeader(NS_LITERAL_CSTRING("Ping-To"), pingTo, false);
  475. }
  476. nsCOMPtr<nsIScriptSecurityManager> sm =
  477. do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
  478. if (sm && info->referrer) {
  479. bool referrerIsSecure;
  480. uint32_t flags = nsIProtocolHandler::URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT;
  481. nsresult rv = NS_URIChainHasFlags(info->referrer, flags, &referrerIsSecure);
  482. // Default to sending less data if NS_URIChainHasFlags() fails.
  483. referrerIsSecure = NS_FAILED(rv) || referrerIsSecure;
  484. bool sameOrigin =
  485. NS_SUCCEEDED(sm->CheckSameOriginURI(info->referrer, aURI, false));
  486. // If both the address of the document containing the hyperlink being
  487. // audited and "ping URL" have the same origin or the document containing
  488. // the hyperlink being audited was not retrieved over an encrypted
  489. // connection, send a Ping-From header.
  490. if (sameOrigin || !referrerIsSecure) {
  491. nsAutoCString pingFrom;
  492. if (NS_SUCCEEDED(info->referrer->GetSpec(pingFrom))) {
  493. httpChan->SetRequestHeader(NS_LITERAL_CSTRING("Ping-From"), pingFrom,
  494. false);
  495. }
  496. }
  497. // If the document containing the hyperlink being audited was not retrieved
  498. // over an encrypted connection and its address does not have the same
  499. // origin as "ping URL", send a referrer.
  500. if (!sameOrigin && !referrerIsSecure) {
  501. httpChan->SetReferrerWithPolicy(info->referrer, info->referrerPolicy);
  502. }
  503. }
  504. nsCOMPtr<nsIUploadChannel2> uploadChan = do_QueryInterface(httpChan);
  505. if (!uploadChan) {
  506. return;
  507. }
  508. NS_NAMED_LITERAL_CSTRING(uploadData, "PING");
  509. nsCOMPtr<nsIInputStream> uploadStream;
  510. NS_NewPostDataStream(getter_AddRefs(uploadStream), false, uploadData);
  511. if (!uploadStream) {
  512. return;
  513. }
  514. uploadChan->ExplicitSetUploadStream(uploadStream,
  515. NS_LITERAL_CSTRING("text/ping"),
  516. uploadData.Length(),
  517. NS_LITERAL_CSTRING("POST"), false);
  518. // The channel needs to have a loadgroup associated with it, so that we can
  519. // cancel the channel and any redirected channels it may create.
  520. nsCOMPtr<nsILoadGroup> loadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
  521. if (!loadGroup) {
  522. return;
  523. }
  524. nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryInterface(info->docShell);
  525. loadGroup->SetNotificationCallbacks(callbacks);
  526. chan->SetLoadGroup(loadGroup);
  527. RefPtr<nsPingListener> pingListener = new nsPingListener();
  528. chan->AsyncOpen2(pingListener);
  529. // Even if AsyncOpen failed, we still count this as a successful ping. It's
  530. // possible that AsyncOpen may have failed after triggering some background
  531. // process that may have written something to the network.
  532. info->numPings++;
  533. // Prevent ping requests from stalling and never being garbage collected...
  534. if (NS_FAILED(pingListener->StartTimeout())) {
  535. // If we failed to setup the timer, then we should just cancel the channel
  536. // because we won't be able to ensure that it goes away in a timely manner.
  537. chan->Cancel(NS_ERROR_ABORT);
  538. return;
  539. }
  540. // if the channel openend successfully, then make the pingListener hold
  541. // a strong reference to the loadgroup which is released in ::OnStopRequest
  542. pingListener->SetLoadGroup(loadGroup);
  543. }
  544. // Spec: http://whatwg.org/specs/web-apps/current-work/#ping
  545. static void
  546. DispatchPings(nsIDocShell* aDocShell,
  547. nsIContent* aContent,
  548. nsIURI* aTarget,
  549. nsIURI* aReferrer,
  550. uint32_t aReferrerPolicy)
  551. {
  552. SendPingInfo info;
  553. if (!PingsEnabled(&info.maxPings, &info.requireSameHost)) {
  554. return;
  555. }
  556. if (info.maxPings == 0) {
  557. return;
  558. }
  559. info.numPings = 0;
  560. info.target = aTarget;
  561. info.referrer = aReferrer;
  562. info.referrerPolicy = aReferrerPolicy;
  563. info.docShell = aDocShell;
  564. ForEachPing(aContent, SendPing, &info);
  565. }
  566. static nsDOMNavigationTiming::Type
  567. ConvertLoadTypeToNavigationType(uint32_t aLoadType)
  568. {
  569. // Not initialized, assume it's normal load.
  570. if (aLoadType == 0) {
  571. aLoadType = LOAD_NORMAL;
  572. }
  573. auto result = nsDOMNavigationTiming::TYPE_RESERVED;
  574. switch (aLoadType) {
  575. case LOAD_NORMAL:
  576. case LOAD_NORMAL_EXTERNAL:
  577. case LOAD_NORMAL_BYPASS_CACHE:
  578. case LOAD_NORMAL_BYPASS_PROXY:
  579. case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
  580. case LOAD_NORMAL_REPLACE:
  581. case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
  582. case LOAD_LINK:
  583. case LOAD_STOP_CONTENT:
  584. case LOAD_REPLACE_BYPASS_CACHE:
  585. result = nsDOMNavigationTiming::TYPE_NAVIGATE;
  586. break;
  587. case LOAD_HISTORY:
  588. result = nsDOMNavigationTiming::TYPE_BACK_FORWARD;
  589. break;
  590. case LOAD_RELOAD_NORMAL:
  591. case LOAD_RELOAD_CHARSET_CHANGE:
  592. case LOAD_RELOAD_BYPASS_CACHE:
  593. case LOAD_RELOAD_BYPASS_PROXY:
  594. case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
  595. case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
  596. result = nsDOMNavigationTiming::TYPE_RELOAD;
  597. break;
  598. case LOAD_STOP_CONTENT_AND_REPLACE:
  599. case LOAD_REFRESH:
  600. case LOAD_BYPASS_HISTORY:
  601. case LOAD_ERROR_PAGE:
  602. case LOAD_PUSHSTATE:
  603. result = nsDOMNavigationTiming::TYPE_RESERVED;
  604. break;
  605. default:
  606. // NS_NOTREACHED("Unexpected load type value");
  607. result = nsDOMNavigationTiming::TYPE_RESERVED;
  608. break;
  609. }
  610. return result;
  611. }
  612. static nsISHEntry* GetRootSHEntry(nsISHEntry* aEntry);
  613. static void
  614. IncreasePrivateDocShellCount()
  615. {
  616. gNumberOfPrivateDocShells++;
  617. if (gNumberOfPrivateDocShells > 1 ||
  618. !XRE_IsContentProcess()) {
  619. return;
  620. }
  621. mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
  622. cc->SendPrivateDocShellsExist(true);
  623. }
  624. static void
  625. DecreasePrivateDocShellCount()
  626. {
  627. MOZ_ASSERT(gNumberOfPrivateDocShells > 0);
  628. gNumberOfPrivateDocShells--;
  629. if (!gNumberOfPrivateDocShells) {
  630. if (XRE_IsContentProcess()) {
  631. dom::ContentChild* cc = dom::ContentChild::GetSingleton();
  632. cc->SendPrivateDocShellsExist(false);
  633. return;
  634. }
  635. nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService();
  636. if (obsvc) {
  637. obsvc->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
  638. }
  639. }
  640. }
  641. static uint64_t gDocshellIDCounter = 0;
  642. nsDocShell::nsDocShell()
  643. : nsDocLoader()
  644. , mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto)
  645. , mTreeOwner(nullptr)
  646. , mChromeEventHandler(nullptr)
  647. , mCharsetReloadState(eCharsetReloadInit)
  648. , mChildOffset(0)
  649. , mBusyFlags(BUSY_FLAGS_NONE)
  650. , mAppType(nsIDocShell::APP_TYPE_UNKNOWN)
  651. , mLoadType(0)
  652. , mMarginWidth(-1)
  653. , mMarginHeight(-1)
  654. , mItemType(typeContent)
  655. , mPreviousTransIndex(-1)
  656. , mLoadedTransIndex(-1)
  657. , mSandboxFlags(0)
  658. , mOrientationLock(eScreenOrientation_None)
  659. , mFullscreenAllowed(CHECK_ATTRIBUTES)
  660. , mCreated(false)
  661. , mAllowSubframes(true)
  662. , mAllowPlugins(true)
  663. , mAllowJavascript(true)
  664. , mAllowMetaRedirects(true)
  665. , mAllowImages(true)
  666. , mAllowMedia(true)
  667. , mAllowDNSPrefetch(true)
  668. , mAllowWindowControl(true)
  669. , mAllowContentRetargeting(true)
  670. , mAllowContentRetargetingOnChildren(true)
  671. , mUseErrorPages(false)
  672. , mObserveErrorPages(true)
  673. , mAllowAuth(true)
  674. , mAllowKeywordFixup(false)
  675. , mIsOffScreenBrowser(false)
  676. , mIsActive(true)
  677. , mDisableMetaRefreshWhenInactive(false)
  678. , mIsPrerendered(false)
  679. , mIsAppTab(false)
  680. , mUseGlobalHistory(false)
  681. , mUseRemoteTabs(false)
  682. , mDeviceSizeIsPageSize(false)
  683. , mWindowDraggingAllowed(false)
  684. , mInFrameSwap(false)
  685. , mInheritPrivateBrowsingId(true)
  686. , mCanExecuteScripts(false)
  687. , mFiredUnloadEvent(false)
  688. , mEODForCurrentDocument(false)
  689. , mURIResultedInDocument(false)
  690. , mIsBeingDestroyed(false)
  691. , mIsExecutingOnLoadHandler(false)
  692. , mIsPrintingOrPP(false)
  693. , mSavingOldViewer(false)
  694. , mAffectPrivateSessionLifetime(true)
  695. , mInvisible(false)
  696. , mHasLoadedNonBlankURI(false)
  697. , mBlankTiming(false)
  698. , mCreatingDocument(false)
  699. #ifdef DEBUG
  700. , mInEnsureScriptEnv(false)
  701. #endif
  702. , mDefaultLoadFlags(nsIRequest::LOAD_NORMAL)
  703. , mFrameType(FRAME_TYPE_REGULAR)
  704. , mPrivateBrowsingId(0)
  705. , mParentCharsetSource(0)
  706. , mJSRunToCompletionDepth(0)
  707. , mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE)
  708. , mStateFloodGuardCount(0)
  709. , mStateFloodGuardReported(false)
  710. , mReloadFloodGuardCount(0)
  711. , mReloadFloodGuardReported(false)
  712. {
  713. AssertOriginAttributesMatchPrivateBrowsing();
  714. mHistoryID = ++gDocshellIDCounter;
  715. if (gDocShellCount++ == 0) {
  716. NS_ASSERTION(sURIFixup == nullptr,
  717. "Huh, sURIFixup not null in first nsDocShell ctor!");
  718. CallGetService(NS_URIFIXUP_CONTRACTID, &sURIFixup);
  719. }
  720. MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p created\n", this));
  721. #ifdef DEBUG
  722. // We're counting the number of |nsDocShells| to help find leaks
  723. ++gNumberOfDocShells;
  724. if (!PR_GetEnv("MOZ_QUIET")) {
  725. printf_stderr("++DOCSHELL %p == %ld [pid = %d] [id = %llu]\n",
  726. (void*)this,
  727. gNumberOfDocShells,
  728. getpid(),
  729. AssertedCast<unsigned long long>(mHistoryID));
  730. }
  731. #endif
  732. }
  733. nsDocShell::~nsDocShell()
  734. {
  735. MOZ_ASSERT(!mObserved);
  736. // Avoid notifying observers while we're in the dtor.
  737. mIsBeingDestroyed = true;
  738. Destroy();
  739. nsCOMPtr<nsISHistoryInternal> shPrivate(do_QueryInterface(mSessionHistory));
  740. if (shPrivate) {
  741. shPrivate->SetRootDocShell(nullptr);
  742. }
  743. if (mContentViewer) {
  744. mContentViewer->Close(nullptr);
  745. mContentViewer->Destroy();
  746. mContentViewer = nullptr;
  747. }
  748. if (--gDocShellCount == 0) {
  749. NS_IF_RELEASE(sURIFixup);
  750. }
  751. if (gDocShellLeakLog) {
  752. MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p destroyed\n", this));
  753. }
  754. #ifdef DEBUG
  755. // We're counting the number of |nsDocShells| to help find leaks
  756. --gNumberOfDocShells;
  757. if (!PR_GetEnv("MOZ_QUIET")) {
  758. printf_stderr("--DOCSHELL %p == %ld [pid = %d] [id = %llu]\n",
  759. (void*)this,
  760. gNumberOfDocShells,
  761. getpid(),
  762. AssertedCast<unsigned long long>(mHistoryID));
  763. }
  764. #endif
  765. }
  766. nsresult
  767. nsDocShell::Init()
  768. {
  769. nsresult rv = nsDocLoader::Init();
  770. NS_ENSURE_SUCCESS(rv, rv);
  771. NS_ASSERTION(mLoadGroup, "Something went wrong!");
  772. mContentListener = new nsDSURIContentListener(this);
  773. rv = mContentListener->Init();
  774. NS_ENSURE_SUCCESS(rv, rv);
  775. // We want to hold a strong ref to the loadgroup, so it better hold a weak
  776. // ref to us... use an InterfaceRequestorProxy to do this.
  777. nsCOMPtr<nsIInterfaceRequestor> proxy =
  778. new InterfaceRequestorProxy(static_cast<nsIInterfaceRequestor*>(this));
  779. mLoadGroup->SetNotificationCallbacks(proxy);
  780. rv = nsDocLoader::AddDocLoaderAsChildOfRoot(this);
  781. NS_ENSURE_SUCCESS(rv, rv);
  782. // Add as |this| a progress listener to itself. A little weird, but
  783. // simpler than reproducing all the listener-notification logic in
  784. // overrides of the various methods via which nsDocLoader can be
  785. // notified. Note that this holds an nsWeakPtr to ourselves, so it's ok.
  786. return AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_DOCUMENT |
  787. nsIWebProgress::NOTIFY_STATE_NETWORK);
  788. }
  789. void
  790. nsDocShell::DestroyChildren()
  791. {
  792. nsCOMPtr<nsIDocShellTreeItem> shell;
  793. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  794. while (iter.HasMore()) {
  795. shell = do_QueryObject(iter.GetNext());
  796. NS_ASSERTION(shell, "docshell has null child");
  797. if (shell) {
  798. shell->SetTreeOwner(nullptr);
  799. }
  800. }
  801. nsDocLoader::DestroyChildren();
  802. }
  803. NS_IMPL_ADDREF_INHERITED(nsDocShell, nsDocLoader)
  804. NS_IMPL_RELEASE_INHERITED(nsDocShell, nsDocLoader)
  805. NS_INTERFACE_MAP_BEGIN(nsDocShell)
  806. NS_INTERFACE_MAP_ENTRY(nsIDocShell)
  807. NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)
  808. NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
  809. NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
  810. NS_INTERFACE_MAP_ENTRY(nsIScrollable)
  811. NS_INTERFACE_MAP_ENTRY(nsITextScroll)
  812. NS_INTERFACE_MAP_ENTRY(nsIDocCharset)
  813. NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)
  814. NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
  815. NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
  816. NS_INTERFACE_MAP_ENTRY(nsIContentViewerContainer)
  817. NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)
  818. NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)
  819. NS_INTERFACE_MAP_ENTRY(nsILoadContext)
  820. NS_INTERFACE_MAP_ENTRY(nsIWebShellServices)
  821. NS_INTERFACE_MAP_ENTRY(nsILinkHandler)
  822. NS_INTERFACE_MAP_ENTRY(nsIClipboardCommands)
  823. NS_INTERFACE_MAP_ENTRY(nsIDOMStorageManager)
  824. NS_INTERFACE_MAP_ENTRY(nsINetworkInterceptController)
  825. NS_INTERFACE_MAP_ENTRY(nsIDeprecationWarner)
  826. NS_INTERFACE_MAP_END_INHERITING(nsDocLoader)
  827. NS_IMETHODIMP
  828. nsDocShell::GetInterface(const nsIID& aIID, void** aSink)
  829. {
  830. NS_PRECONDITION(aSink, "null out param");
  831. *aSink = nullptr;
  832. if (aIID.Equals(NS_GET_IID(nsICommandManager))) {
  833. NS_ENSURE_SUCCESS(EnsureCommandHandler(), NS_ERROR_FAILURE);
  834. *aSink = mCommandManager;
  835. } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener))) {
  836. *aSink = mContentListener;
  837. } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)) ||
  838. aIID.Equals(NS_GET_IID(nsIGlobalObject)) ||
  839. aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)) ||
  840. aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)) ||
  841. aIID.Equals(NS_GET_IID(nsIDOMWindow)) ||
  842. aIID.Equals(NS_GET_IID(nsIDOMWindowInternal))) &&
  843. NS_SUCCEEDED(EnsureScriptEnvironment())) {
  844. return mScriptGlobal->QueryInterface(aIID, aSink);
  845. } else if (aIID.Equals(NS_GET_IID(nsIDOMDocument)) &&
  846. NS_SUCCEEDED(EnsureContentViewer())) {
  847. mContentViewer->GetDOMDocument((nsIDOMDocument**)aSink);
  848. return *aSink ? NS_OK : NS_NOINTERFACE;
  849. } else if (aIID.Equals(NS_GET_IID(nsIDocument)) &&
  850. NS_SUCCEEDED(EnsureContentViewer())) {
  851. nsCOMPtr<nsIDocument> doc = mContentViewer->GetDocument();
  852. doc.forget(aSink);
  853. return *aSink ? NS_OK : NS_NOINTERFACE;
  854. } else if (aIID.Equals(NS_GET_IID(nsIApplicationCacheContainer))) {
  855. *aSink = nullptr;
  856. // Return application cache associated with this docshell, if any
  857. nsCOMPtr<nsIContentViewer> contentViewer;
  858. GetContentViewer(getter_AddRefs(contentViewer));
  859. if (!contentViewer) {
  860. return NS_ERROR_NO_INTERFACE;
  861. }
  862. nsCOMPtr<nsIDOMDocument> domDoc;
  863. contentViewer->GetDOMDocument(getter_AddRefs(domDoc));
  864. NS_ASSERTION(domDoc, "Should have a document.");
  865. if (!domDoc) {
  866. return NS_ERROR_NO_INTERFACE;
  867. }
  868. #if defined(DEBUG)
  869. MOZ_LOG(gDocShellLog, LogLevel::Debug,
  870. ("nsDocShell[%p]: returning app cache container %p",
  871. this, domDoc.get()));
  872. #endif
  873. return domDoc->QueryInterface(aIID, aSink);
  874. } else if (aIID.Equals(NS_GET_IID(nsIPrompt)) &&
  875. NS_SUCCEEDED(EnsureScriptEnvironment())) {
  876. nsresult rv;
  877. nsCOMPtr<nsIWindowWatcher> wwatch =
  878. do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
  879. NS_ENSURE_SUCCESS(rv, rv);
  880. // Get the an auth prompter for our window so that the parenting
  881. // of the dialogs works as it should when using tabs.
  882. nsIPrompt* prompt;
  883. rv = wwatch->GetNewPrompter(mScriptGlobal->AsOuter(), &prompt);
  884. NS_ENSURE_SUCCESS(rv, rv);
  885. *aSink = prompt;
  886. return NS_OK;
  887. } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)) ||
  888. aIID.Equals(NS_GET_IID(nsIAuthPrompt2))) {
  889. return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink)) ?
  890. NS_OK : NS_NOINTERFACE;
  891. } else if (aIID.Equals(NS_GET_IID(nsISHistory))) {
  892. nsCOMPtr<nsISHistory> shistory;
  893. nsresult rv = GetSessionHistory(getter_AddRefs(shistory));
  894. if (NS_SUCCEEDED(rv) && shistory) {
  895. shistory.forget(aSink);
  896. return NS_OK;
  897. }
  898. return NS_NOINTERFACE;
  899. } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind))) {
  900. nsresult rv = EnsureFind();
  901. if (NS_FAILED(rv)) {
  902. return rv;
  903. }
  904. *aSink = mFind;
  905. NS_ADDREF((nsISupports*)*aSink);
  906. return NS_OK;
  907. } else if (aIID.Equals(NS_GET_IID(nsIEditingSession))) {
  908. nsCOMPtr<nsIEditingSession> es;
  909. GetEditingSession(getter_AddRefs(es));
  910. es.forget(aSink);
  911. return *aSink ? NS_OK : NS_NOINTERFACE;
  912. } else if (aIID.Equals(NS_GET_IID(nsIClipboardDragDropHookList)) &&
  913. NS_SUCCEEDED(EnsureTransferableHookData())) {
  914. *aSink = mTransferableHookData;
  915. NS_ADDREF((nsISupports*)*aSink);
  916. return NS_OK;
  917. } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay))) {
  918. nsIPresShell* shell = GetPresShell();
  919. if (shell) {
  920. return shell->QueryInterface(aIID, aSink);
  921. }
  922. } else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner))) {
  923. nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
  924. nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
  925. if (NS_SUCCEEDED(rv) && treeOwner) {
  926. return treeOwner->QueryInterface(aIID, aSink);
  927. }
  928. } else if (aIID.Equals(NS_GET_IID(nsITabChild))) {
  929. *aSink = GetTabChild().take();
  930. return *aSink ? NS_OK : NS_ERROR_FAILURE;
  931. } else if (aIID.Equals(NS_GET_IID(nsIContentFrameMessageManager))) {
  932. nsCOMPtr<nsITabChild> tabChild =
  933. do_GetInterface(static_cast<nsIDocShell*>(this));
  934. nsCOMPtr<nsIContentFrameMessageManager> mm;
  935. if (tabChild) {
  936. tabChild->GetMessageManager(getter_AddRefs(mm));
  937. } else {
  938. if (nsPIDOMWindowOuter* win = GetWindow()) {
  939. mm = do_QueryInterface(win->GetParentTarget());
  940. }
  941. }
  942. *aSink = mm.get();
  943. } else {
  944. return nsDocLoader::GetInterface(aIID, aSink);
  945. }
  946. NS_IF_ADDREF(((nsISupports*)*aSink));
  947. return *aSink ? NS_OK : NS_NOINTERFACE;
  948. }
  949. uint32_t
  950. nsDocShell::ConvertDocShellLoadInfoToLoadType(
  951. nsDocShellInfoLoadType aDocShellLoadType)
  952. {
  953. uint32_t loadType = LOAD_NORMAL;
  954. switch (aDocShellLoadType) {
  955. case nsIDocShellLoadInfo::loadNormal:
  956. loadType = LOAD_NORMAL;
  957. break;
  958. case nsIDocShellLoadInfo::loadNormalReplace:
  959. loadType = LOAD_NORMAL_REPLACE;
  960. break;
  961. case nsIDocShellLoadInfo::loadNormalExternal:
  962. loadType = LOAD_NORMAL_EXTERNAL;
  963. break;
  964. case nsIDocShellLoadInfo::loadHistory:
  965. loadType = LOAD_HISTORY;
  966. break;
  967. case nsIDocShellLoadInfo::loadNormalBypassCache:
  968. loadType = LOAD_NORMAL_BYPASS_CACHE;
  969. break;
  970. case nsIDocShellLoadInfo::loadNormalBypassProxy:
  971. loadType = LOAD_NORMAL_BYPASS_PROXY;
  972. break;
  973. case nsIDocShellLoadInfo::loadNormalBypassProxyAndCache:
  974. loadType = LOAD_NORMAL_BYPASS_PROXY_AND_CACHE;
  975. break;
  976. case nsIDocShellLoadInfo::loadNormalAllowMixedContent:
  977. loadType = LOAD_NORMAL_ALLOW_MIXED_CONTENT;
  978. break;
  979. case nsIDocShellLoadInfo::loadReloadNormal:
  980. loadType = LOAD_RELOAD_NORMAL;
  981. break;
  982. case nsIDocShellLoadInfo::loadReloadCharsetChange:
  983. loadType = LOAD_RELOAD_CHARSET_CHANGE;
  984. break;
  985. case nsIDocShellLoadInfo::loadReloadBypassCache:
  986. loadType = LOAD_RELOAD_BYPASS_CACHE;
  987. break;
  988. case nsIDocShellLoadInfo::loadReloadBypassProxy:
  989. loadType = LOAD_RELOAD_BYPASS_PROXY;
  990. break;
  991. case nsIDocShellLoadInfo::loadReloadBypassProxyAndCache:
  992. loadType = LOAD_RELOAD_BYPASS_PROXY_AND_CACHE;
  993. break;
  994. case nsIDocShellLoadInfo::loadLink:
  995. loadType = LOAD_LINK;
  996. break;
  997. case nsIDocShellLoadInfo::loadRefresh:
  998. loadType = LOAD_REFRESH;
  999. break;
  1000. case nsIDocShellLoadInfo::loadBypassHistory:
  1001. loadType = LOAD_BYPASS_HISTORY;
  1002. break;
  1003. case nsIDocShellLoadInfo::loadStopContent:
  1004. loadType = LOAD_STOP_CONTENT;
  1005. break;
  1006. case nsIDocShellLoadInfo::loadStopContentAndReplace:
  1007. loadType = LOAD_STOP_CONTENT_AND_REPLACE;
  1008. break;
  1009. case nsIDocShellLoadInfo::loadPushState:
  1010. loadType = LOAD_PUSHSTATE;
  1011. break;
  1012. case nsIDocShellLoadInfo::loadReplaceBypassCache:
  1013. loadType = LOAD_REPLACE_BYPASS_CACHE;
  1014. break;
  1015. case nsIDocShellLoadInfo::loadReloadMixedContent:
  1016. loadType = LOAD_RELOAD_ALLOW_MIXED_CONTENT;
  1017. break;
  1018. default:
  1019. NS_NOTREACHED("Unexpected nsDocShellInfoLoadType value");
  1020. }
  1021. return loadType;
  1022. }
  1023. nsDocShellInfoLoadType
  1024. nsDocShell::ConvertLoadTypeToDocShellLoadInfo(uint32_t aLoadType)
  1025. {
  1026. nsDocShellInfoLoadType docShellLoadType = nsIDocShellLoadInfo::loadNormal;
  1027. switch (aLoadType) {
  1028. case LOAD_NORMAL:
  1029. docShellLoadType = nsIDocShellLoadInfo::loadNormal;
  1030. break;
  1031. case LOAD_NORMAL_REPLACE:
  1032. docShellLoadType = nsIDocShellLoadInfo::loadNormalReplace;
  1033. break;
  1034. case LOAD_NORMAL_EXTERNAL:
  1035. docShellLoadType = nsIDocShellLoadInfo::loadNormalExternal;
  1036. break;
  1037. case LOAD_NORMAL_BYPASS_CACHE:
  1038. docShellLoadType = nsIDocShellLoadInfo::loadNormalBypassCache;
  1039. break;
  1040. case LOAD_NORMAL_BYPASS_PROXY:
  1041. docShellLoadType = nsIDocShellLoadInfo::loadNormalBypassProxy;
  1042. break;
  1043. case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
  1044. docShellLoadType = nsIDocShellLoadInfo::loadNormalBypassProxyAndCache;
  1045. break;
  1046. case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
  1047. docShellLoadType = nsIDocShellLoadInfo::loadNormalAllowMixedContent;
  1048. break;
  1049. case LOAD_HISTORY:
  1050. docShellLoadType = nsIDocShellLoadInfo::loadHistory;
  1051. break;
  1052. case LOAD_RELOAD_NORMAL:
  1053. docShellLoadType = nsIDocShellLoadInfo::loadReloadNormal;
  1054. break;
  1055. case LOAD_RELOAD_CHARSET_CHANGE:
  1056. docShellLoadType = nsIDocShellLoadInfo::loadReloadCharsetChange;
  1057. break;
  1058. case LOAD_RELOAD_BYPASS_CACHE:
  1059. docShellLoadType = nsIDocShellLoadInfo::loadReloadBypassCache;
  1060. break;
  1061. case LOAD_RELOAD_BYPASS_PROXY:
  1062. docShellLoadType = nsIDocShellLoadInfo::loadReloadBypassProxy;
  1063. break;
  1064. case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
  1065. docShellLoadType = nsIDocShellLoadInfo::loadReloadBypassProxyAndCache;
  1066. break;
  1067. case LOAD_LINK:
  1068. docShellLoadType = nsIDocShellLoadInfo::loadLink;
  1069. break;
  1070. case LOAD_REFRESH:
  1071. docShellLoadType = nsIDocShellLoadInfo::loadRefresh;
  1072. break;
  1073. case LOAD_BYPASS_HISTORY:
  1074. case LOAD_ERROR_PAGE:
  1075. docShellLoadType = nsIDocShellLoadInfo::loadBypassHistory;
  1076. break;
  1077. case LOAD_STOP_CONTENT:
  1078. docShellLoadType = nsIDocShellLoadInfo::loadStopContent;
  1079. break;
  1080. case LOAD_STOP_CONTENT_AND_REPLACE:
  1081. docShellLoadType = nsIDocShellLoadInfo::loadStopContentAndReplace;
  1082. break;
  1083. case LOAD_PUSHSTATE:
  1084. docShellLoadType = nsIDocShellLoadInfo::loadPushState;
  1085. break;
  1086. case LOAD_REPLACE_BYPASS_CACHE:
  1087. docShellLoadType = nsIDocShellLoadInfo::loadReplaceBypassCache;
  1088. break;
  1089. case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
  1090. docShellLoadType = nsIDocShellLoadInfo::loadReloadMixedContent;
  1091. break;
  1092. default:
  1093. NS_NOTREACHED("Unexpected load type value");
  1094. }
  1095. return docShellLoadType;
  1096. }
  1097. NS_IMETHODIMP
  1098. nsDocShell::LoadURI(nsIURI* aURI,
  1099. nsIDocShellLoadInfo* aLoadInfo,
  1100. uint32_t aLoadFlags,
  1101. bool aFirstParty)
  1102. {
  1103. NS_PRECONDITION(aLoadInfo || (aLoadFlags & EXTRA_LOAD_FLAGS) == 0,
  1104. "Unexpected flags");
  1105. NS_PRECONDITION((aLoadFlags & 0xf) == 0, "Should not have these flags set");
  1106. // Note: we allow loads to get through here even if mFiredUnloadEvent is
  1107. // true; that case will get handled in LoadInternal or LoadHistoryEntry,
  1108. // so we pass false as the second parameter to IsNavigationAllowed.
  1109. // However, we don't allow the page to change location *in the middle of*
  1110. // firing beforeunload, so we do need to check if *beforeunload* is currently
  1111. // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP.
  1112. if (!IsNavigationAllowed(true, false)) {
  1113. return NS_OK; // JS may not handle returning of an error code
  1114. }
  1115. nsCOMPtr<nsIURI> referrer;
  1116. nsCOMPtr<nsIURI> originalURI;
  1117. bool loadReplace = false;
  1118. bool isFromProcessingFrameAttributes = false;
  1119. nsCOMPtr<nsIInputStream> postStream;
  1120. nsCOMPtr<nsIInputStream> headersStream;
  1121. nsCOMPtr<nsIPrincipal> triggeringPrincipal;
  1122. bool inheritPrincipal = false;
  1123. bool principalIsExplicit = false;
  1124. bool sendReferrer = true;
  1125. uint32_t referrerPolicy = mozilla::net::RP_Default;
  1126. bool isSrcdoc = false;
  1127. nsCOMPtr<nsISHEntry> shEntry;
  1128. nsXPIDLString target;
  1129. nsAutoString srcdoc;
  1130. bool forceAllowDataURI = false;
  1131. nsCOMPtr<nsIDocShell> sourceDocShell;
  1132. nsCOMPtr<nsIURI> baseURI;
  1133. uint32_t loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
  1134. NS_ENSURE_ARG(aURI);
  1135. if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
  1136. mItemType == typeContent && !NS_IsAboutBlank(aURI)) {
  1137. StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
  1138. }
  1139. // Extract the info from the DocShellLoadInfo struct...
  1140. if (aLoadInfo) {
  1141. aLoadInfo->GetReferrer(getter_AddRefs(referrer));
  1142. aLoadInfo->GetOriginalURI(getter_AddRefs(originalURI));
  1143. aLoadInfo->GetLoadReplace(&loadReplace);
  1144. aLoadInfo->GetIsFromProcessingFrameAttributes(&isFromProcessingFrameAttributes);
  1145. nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal;
  1146. aLoadInfo->GetLoadType(&lt);
  1147. // Get the appropriate loadType from nsIDocShellLoadInfo type
  1148. loadType = ConvertDocShellLoadInfoToLoadType(lt);
  1149. aLoadInfo->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
  1150. aLoadInfo->GetInheritPrincipal(&inheritPrincipal);
  1151. aLoadInfo->GetPrincipalIsExplicit(&principalIsExplicit);
  1152. aLoadInfo->GetSHEntry(getter_AddRefs(shEntry));
  1153. aLoadInfo->GetTarget(getter_Copies(target));
  1154. aLoadInfo->GetPostDataStream(getter_AddRefs(postStream));
  1155. aLoadInfo->GetHeadersStream(getter_AddRefs(headersStream));
  1156. aLoadInfo->GetSendReferrer(&sendReferrer);
  1157. aLoadInfo->GetReferrerPolicy(&referrerPolicy);
  1158. aLoadInfo->GetIsSrcdocLoad(&isSrcdoc);
  1159. aLoadInfo->GetSrcdocData(srcdoc);
  1160. aLoadInfo->GetSourceDocShell(getter_AddRefs(sourceDocShell));
  1161. aLoadInfo->GetBaseURI(getter_AddRefs(baseURI));
  1162. aLoadInfo->GetForceAllowDataURI(&forceAllowDataURI);
  1163. }
  1164. #if defined(DEBUG)
  1165. if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)) {
  1166. nsAutoCString uristr;
  1167. aURI->GetAsciiSpec(uristr);
  1168. MOZ_LOG(gDocShellLog, LogLevel::Debug,
  1169. ("nsDocShell[%p]: loading %s with flags 0x%08x",
  1170. this, uristr.get(), aLoadFlags));
  1171. }
  1172. #endif
  1173. if (!shEntry &&
  1174. !LOAD_TYPE_HAS_FLAGS(loadType, LOAD_FLAGS_REPLACE_HISTORY)) {
  1175. // First verify if this is a subframe.
  1176. nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
  1177. GetSameTypeParent(getter_AddRefs(parentAsItem));
  1178. nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
  1179. uint32_t parentLoadType;
  1180. if (parentDS && parentDS != static_cast<nsIDocShell*>(this)) {
  1181. /* OK. It is a subframe. Checkout the
  1182. * parent's loadtype. If the parent was loaded thro' a history
  1183. * mechanism, then get the SH entry for the child from the parent.
  1184. * This is done to restore frameset navigation while going back/forward.
  1185. * If the parent was loaded through any other loadType, set the
  1186. * child's loadType too accordingly, so that session history does not
  1187. * get confused.
  1188. */
  1189. // Get the parent's load type
  1190. parentDS->GetLoadType(&parentLoadType);
  1191. // Get the ShEntry for the child from the parent
  1192. nsCOMPtr<nsISHEntry> currentSH;
  1193. bool oshe = false;
  1194. parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
  1195. bool dynamicallyAddedChild = mDynamicallyCreated;
  1196. if (!dynamicallyAddedChild && !oshe && currentSH) {
  1197. currentSH->HasDynamicallyAddedChild(&dynamicallyAddedChild);
  1198. }
  1199. if (!dynamicallyAddedChild) {
  1200. // Only use the old SHEntry, if we're sure enough that
  1201. // it wasn't originally for some other frame.
  1202. parentDS->GetChildSHEntry(mChildOffset, getter_AddRefs(shEntry));
  1203. }
  1204. // Make some decisions on the child frame's loadType based on the
  1205. // parent's loadType.
  1206. if (!mCurrentURI) {
  1207. // This is a newly created frame. Check for exception cases first.
  1208. // By default the subframe will inherit the parent's loadType.
  1209. if (shEntry && (parentLoadType == LOAD_NORMAL ||
  1210. parentLoadType == LOAD_LINK ||
  1211. parentLoadType == LOAD_NORMAL_EXTERNAL)) {
  1212. // The parent was loaded normally. In this case, this *brand new*
  1213. // child really shouldn't have a SHEntry. If it does, it could be
  1214. // because the parent is replacing an existing frame with a new frame,
  1215. // in the onLoadHandler. We don't want this url to get into session
  1216. // history. Clear off shEntry, and set load type to
  1217. // LOAD_BYPASS_HISTORY.
  1218. bool inOnLoadHandler = false;
  1219. parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
  1220. if (inOnLoadHandler) {
  1221. loadType = LOAD_NORMAL_REPLACE;
  1222. shEntry = nullptr;
  1223. }
  1224. } else if (parentLoadType == LOAD_REFRESH) {
  1225. // Clear shEntry. For refresh loads, we have to load
  1226. // what comes thro' the pipe, not what's in history.
  1227. shEntry = nullptr;
  1228. } else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
  1229. (shEntry &&
  1230. ((parentLoadType & LOAD_CMD_HISTORY) ||
  1231. (parentLoadType == LOAD_RELOAD_NORMAL) ||
  1232. (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE)))) {
  1233. // If the parent url, bypassed history or was loaded from
  1234. // history, pass on the parent's loadType to the new child
  1235. // frame too, so that the child frame will also
  1236. // avoid getting into history.
  1237. loadType = parentLoadType;
  1238. } else if (parentLoadType == LOAD_ERROR_PAGE) {
  1239. // If the parent document is an error page, we don't
  1240. // want to update global/session history. However,
  1241. // this child frame is not an error page.
  1242. loadType = LOAD_BYPASS_HISTORY;
  1243. } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
  1244. (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
  1245. (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
  1246. // the new frame should inherit the parent's load type so that it also
  1247. // bypasses the cache and/or proxy
  1248. loadType = parentLoadType;
  1249. }
  1250. } else {
  1251. // This is a pre-existing subframe. If the load was not originally
  1252. // initiated by session history, (if (!shEntry) condition succeeded) and
  1253. // mCurrentURI is not null, it is possible that a parent's onLoadHandler
  1254. // or even self's onLoadHandler is loading a new page in this child.
  1255. // Check parent's and self's busy flag and if it is set, we don't want
  1256. // this onLoadHandler load to get in to session history.
  1257. uint32_t parentBusy = BUSY_FLAGS_NONE;
  1258. uint32_t selfBusy = BUSY_FLAGS_NONE;
  1259. parentDS->GetBusyFlags(&parentBusy);
  1260. GetBusyFlags(&selfBusy);
  1261. if (parentBusy & BUSY_FLAGS_BUSY ||
  1262. selfBusy & BUSY_FLAGS_BUSY) {
  1263. loadType = LOAD_NORMAL_REPLACE;
  1264. shEntry = nullptr;
  1265. }
  1266. }
  1267. } // parentDS
  1268. else {
  1269. // This is the root docshell. If we got here while
  1270. // executing an onLoad Handler,this load will not go
  1271. // into session history.
  1272. bool inOnLoadHandler = false;
  1273. GetIsExecutingOnLoadHandler(&inOnLoadHandler);
  1274. if (inOnLoadHandler) {
  1275. loadType = LOAD_NORMAL_REPLACE;
  1276. }
  1277. }
  1278. } // !shEntry
  1279. if (shEntry) {
  1280. #ifdef DEBUG
  1281. MOZ_LOG(gDocShellLog, LogLevel::Debug,
  1282. ("nsDocShell[%p]: loading from session history", this));
  1283. #endif
  1284. return LoadHistoryEntry(shEntry, loadType);
  1285. }
  1286. // On history navigation via Back/Forward buttons, don't execute
  1287. // automatic JavaScript redirection such as |location.href = ...| or
  1288. // |window.open()|
  1289. //
  1290. // LOAD_NORMAL: window.open(...) etc.
  1291. // LOAD_STOP_CONTENT: location.href = ..., location.assign(...)
  1292. if ((loadType == LOAD_NORMAL || loadType == LOAD_STOP_CONTENT) &&
  1293. ShouldBlockLoadingForBackButton()) {
  1294. return NS_OK;
  1295. }
  1296. // Perform the load...
  1297. // We need a principalToInherit.
  1298. //
  1299. // If principalIsExplicit is not set there are 4 possibilities:
  1300. // (1) If the system principal or an expanded principal was passed
  1301. // in and we're a typeContent docshell, inherit the principal
  1302. // from the current document instead.
  1303. // (2) In all other cases when the principal passed in is not null,
  1304. // use that principal.
  1305. // (3) If the caller has allowed inheriting from the current document,
  1306. // or if we're being called from system code (eg chrome JS or pure
  1307. // C++) then inheritPrincipal should be true and InternalLoad will get
  1308. // a principal from the current document. If none of these things are
  1309. // true, then
  1310. // (4) we don't pass a principal into the channel, and a principal will be
  1311. // created later from the channel's internal data.
  1312. //
  1313. // If principalIsExplicit *is* set, there are 4 possibilities
  1314. // (1) If the system principal or an expanded principal was passed in
  1315. // and we're a typeContent docshell, return an error.
  1316. // (2) In all other cases when the principal passed in is not null,
  1317. // use that principal.
  1318. // (3) If the caller has allowed inheriting from the current document,
  1319. // then inheritPrincipal should be true and InternalLoad will get
  1320. // a principal from the current document. If none of these things are
  1321. // true, then
  1322. // (4) we dont' pass a principal into the channel, and a principal will be
  1323. // created later from the channel's internal data.
  1324. nsCOMPtr<nsIPrincipal> principalToInherit = triggeringPrincipal;
  1325. if (principalToInherit && mItemType != typeChrome) {
  1326. if (nsContentUtils::IsSystemPrincipal(principalToInherit)) {
  1327. if (principalIsExplicit) {
  1328. return NS_ERROR_DOM_SECURITY_ERR;
  1329. }
  1330. principalToInherit = nullptr;
  1331. inheritPrincipal = true;
  1332. } else if (nsContentUtils::IsExpandedPrincipal(principalToInherit)) {
  1333. if (principalIsExplicit) {
  1334. return NS_ERROR_DOM_SECURITY_ERR;
  1335. }
  1336. // Don't inherit from the current page. Just do the safe thing
  1337. // and pretend that we were loaded by a nullprincipal.
  1338. //
  1339. // We didn't inherit OriginAttributes here as ExpandedPrincipal doesn't
  1340. // have origin attributes.
  1341. principalToInherit = nsNullPrincipal::CreateWithInheritedAttributes(this);
  1342. inheritPrincipal = false;
  1343. }
  1344. }
  1345. if (!principalToInherit && !inheritPrincipal && !principalIsExplicit) {
  1346. // See if there's system or chrome JS code running
  1347. inheritPrincipal = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
  1348. }
  1349. if (aLoadFlags & LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL) {
  1350. inheritPrincipal = false;
  1351. principalToInherit = nsNullPrincipal::CreateWithInheritedAttributes(this);
  1352. }
  1353. // If the triggeringPrincipal is not passed explicitly, we first try to create
  1354. // a principal from the referrer, since the referrer URI reflects the web origin
  1355. // that triggered the load. If there is no referrer URI, we fall back to using
  1356. // the SystemPrincipal. It's safe to assume that no provided triggeringPrincipal
  1357. // and no referrer simulate a load that was triggered by the system.
  1358. // It's important to note that this block of code needs to appear *after* the block
  1359. // where we munge the principalToInherit, because otherwise we would never enter
  1360. // code blocks checking if the principalToInherit is null and we will end up with
  1361. // a wrong inheritPrincipal flag.
  1362. if (!triggeringPrincipal) {
  1363. if (referrer) {
  1364. nsresult rv = CreatePrincipalFromReferrer(referrer,
  1365. getter_AddRefs(triggeringPrincipal));
  1366. NS_ENSURE_SUCCESS(rv, rv);
  1367. }
  1368. else {
  1369. triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
  1370. }
  1371. }
  1372. uint32_t flags = 0;
  1373. if (inheritPrincipal) {
  1374. flags |= INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL;
  1375. }
  1376. if (!sendReferrer) {
  1377. flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
  1378. }
  1379. if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
  1380. flags |= INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
  1381. }
  1382. if (aLoadFlags & LOAD_FLAGS_FIRST_LOAD) {
  1383. flags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
  1384. }
  1385. if (aLoadFlags & LOAD_FLAGS_BYPASS_CLASSIFIER) {
  1386. flags |= INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
  1387. }
  1388. if (aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_COOKIES) {
  1389. flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
  1390. }
  1391. if (isSrcdoc) {
  1392. flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
  1393. }
  1394. if (forceAllowDataURI) {
  1395. flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
  1396. }
  1397. return InternalLoad(aURI,
  1398. originalURI,
  1399. loadReplace,
  1400. isFromProcessingFrameAttributes,
  1401. referrer,
  1402. referrerPolicy,
  1403. triggeringPrincipal,
  1404. principalToInherit,
  1405. flags,
  1406. target,
  1407. nullptr, // No type hint
  1408. NullString(), // No forced download
  1409. postStream,
  1410. headersStream,
  1411. loadType,
  1412. nullptr, // No SHEntry
  1413. aFirstParty,
  1414. srcdoc,
  1415. sourceDocShell,
  1416. baseURI,
  1417. nullptr, // No nsIDocShell
  1418. nullptr); // No nsIRequest
  1419. }
  1420. NS_IMETHODIMP
  1421. nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI,
  1422. const nsACString& aContentType,
  1423. const nsACString& aContentCharset,
  1424. nsIDocShellLoadInfo* aLoadInfo)
  1425. {
  1426. NS_ENSURE_ARG(aStream);
  1427. mAllowKeywordFixup = false;
  1428. // if the caller doesn't pass in a URI we need to create a dummy URI. necko
  1429. // currently requires a URI in various places during the load. Some consumers
  1430. // do as well.
  1431. nsCOMPtr<nsIURI> uri = aURI;
  1432. if (!uri) {
  1433. // HACK ALERT
  1434. nsresult rv = NS_OK;
  1435. uri = do_CreateInstance(NS_SIMPLEURI_CONTRACTID, &rv);
  1436. if (NS_FAILED(rv)) {
  1437. return rv;
  1438. }
  1439. // Make sure that the URI spec "looks" like a protocol and path...
  1440. // For now, just use a bogus protocol called "internal"
  1441. rv = uri->SetSpec(NS_LITERAL_CSTRING("internal:load-stream"));
  1442. if (NS_FAILED(rv)) {
  1443. return rv;
  1444. }
  1445. }
  1446. uint32_t loadType = LOAD_NORMAL;
  1447. nsCOMPtr<nsIPrincipal> triggeringPrincipal;
  1448. if (aLoadInfo) {
  1449. nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal;
  1450. (void)aLoadInfo->GetLoadType(&lt);
  1451. // Get the appropriate LoadType from nsIDocShellLoadInfo type
  1452. loadType = ConvertDocShellLoadInfoToLoadType(lt);
  1453. aLoadInfo->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
  1454. }
  1455. NS_ENSURE_SUCCESS(Stop(nsIWebNavigation::STOP_NETWORK), NS_ERROR_FAILURE);
  1456. mLoadType = loadType;
  1457. if (!triggeringPrincipal) {
  1458. triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
  1459. }
  1460. // build up a channel for this stream.
  1461. nsCOMPtr<nsIChannel> channel;
  1462. nsresult rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
  1463. uri,
  1464. aStream,
  1465. triggeringPrincipal,
  1466. nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
  1467. nsIContentPolicy::TYPE_OTHER,
  1468. aContentType,
  1469. aContentCharset);
  1470. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1471. nsCOMPtr<nsIURILoader> uriLoader(do_GetService(NS_URI_LOADER_CONTRACTID));
  1472. NS_ENSURE_TRUE(uriLoader, NS_ERROR_FAILURE);
  1473. NS_ENSURE_SUCCESS(DoChannelLoad(channel, uriLoader, false),
  1474. NS_ERROR_FAILURE);
  1475. return NS_OK;
  1476. }
  1477. NS_IMETHODIMP
  1478. nsDocShell::CreateLoadInfo(nsIDocShellLoadInfo** aLoadInfo)
  1479. {
  1480. nsDocShellLoadInfo* loadInfo = new nsDocShellLoadInfo();
  1481. nsCOMPtr<nsIDocShellLoadInfo> localRef(loadInfo);
  1482. localRef.forget(aLoadInfo);
  1483. return NS_OK;
  1484. }
  1485. /*
  1486. * Reset state to a new content model within the current document and the
  1487. * document viewer. Called by the document before initiating an out of band
  1488. * document.write().
  1489. */
  1490. NS_IMETHODIMP
  1491. nsDocShell::PrepareForNewContentModel()
  1492. {
  1493. mEODForCurrentDocument = false;
  1494. return NS_OK;
  1495. }
  1496. NS_IMETHODIMP
  1497. nsDocShell::FirePageHideNotification(bool aIsUnload)
  1498. {
  1499. if (mContentViewer && !mFiredUnloadEvent) {
  1500. // Keep an explicit reference since calling PageHide could release
  1501. // mContentViewer
  1502. nsCOMPtr<nsIContentViewer> contentViewer(mContentViewer);
  1503. mFiredUnloadEvent = true;
  1504. if (mTiming) {
  1505. mTiming->NotifyUnloadEventStart();
  1506. }
  1507. contentViewer->PageHide(aIsUnload);
  1508. if (mTiming) {
  1509. mTiming->NotifyUnloadEventEnd();
  1510. }
  1511. AutoTArray<nsCOMPtr<nsIDocShell>, 8> kids;
  1512. uint32_t n = mChildList.Length();
  1513. kids.SetCapacity(n);
  1514. for (uint32_t i = 0; i < n; i++) {
  1515. kids.AppendElement(do_QueryInterface(ChildAt(i)));
  1516. }
  1517. n = kids.Length();
  1518. for (uint32_t i = 0; i < n; ++i) {
  1519. if (kids[i]) {
  1520. kids[i]->FirePageHideNotification(aIsUnload);
  1521. }
  1522. }
  1523. // Now make sure our editor, if any, is detached before we go
  1524. // any farther.
  1525. DetachEditorFromWindow();
  1526. }
  1527. return NS_OK;
  1528. }
  1529. void
  1530. nsDocShell::MaybeInitTiming()
  1531. {
  1532. if (mTiming && !mBlankTiming) {
  1533. return;
  1534. }
  1535. if (mScriptGlobal && mBlankTiming) {
  1536. nsPIDOMWindowInner* innerWin =
  1537. mScriptGlobal->AsOuter()->GetCurrentInnerWindow();
  1538. if (innerWin && innerWin->GetPerformance()) {
  1539. mTiming = innerWin->GetPerformance()->GetDOMTiming();
  1540. mBlankTiming = false;
  1541. }
  1542. }
  1543. if (!mTiming) {
  1544. mTiming = new nsDOMNavigationTiming();
  1545. }
  1546. mTiming->NotifyNavigationStart(
  1547. mIsActive ? nsDOMNavigationTiming::DocShellState::eActive
  1548. : nsDOMNavigationTiming::DocShellState::eInactive);
  1549. }
  1550. //
  1551. // Bug 13871: Prevent frameset spoofing
  1552. //
  1553. // This routine answers: 'Is origin's document from same domain as
  1554. // target's document?'
  1555. //
  1556. // file: uris are considered the same domain for the purpose of
  1557. // frame navigation regardless of script accessibility (bug 420425)
  1558. //
  1559. /* static */ bool
  1560. nsDocShell::ValidateOrigin(nsIDocShellTreeItem* aOriginTreeItem,
  1561. nsIDocShellTreeItem* aTargetTreeItem)
  1562. {
  1563. // We want to bypass this check for chrome callers, but only if there's
  1564. // JS on the stack. System callers still need to do it.
  1565. if (nsContentUtils::GetCurrentJSContext() &&
  1566. nsContentUtils::IsCallerChrome()) {
  1567. return true;
  1568. }
  1569. MOZ_ASSERT(aOriginTreeItem && aTargetTreeItem, "need two docshells");
  1570. // Get origin document principal
  1571. nsCOMPtr<nsIDocument> originDocument = aOriginTreeItem->GetDocument();
  1572. NS_ENSURE_TRUE(originDocument, false);
  1573. // Get target principal
  1574. nsCOMPtr<nsIDocument> targetDocument = aTargetTreeItem->GetDocument();
  1575. NS_ENSURE_TRUE(targetDocument, false);
  1576. bool equal;
  1577. nsresult rv = originDocument->NodePrincipal()->Equals(
  1578. targetDocument->NodePrincipal(), &equal);
  1579. if (NS_SUCCEEDED(rv) && equal) {
  1580. return true;
  1581. }
  1582. // Not strictly equal, special case if both are file: uris
  1583. bool originIsFile = false;
  1584. bool targetIsFile = false;
  1585. nsCOMPtr<nsIURI> originURI;
  1586. nsCOMPtr<nsIURI> targetURI;
  1587. nsCOMPtr<nsIURI> innerOriginURI;
  1588. nsCOMPtr<nsIURI> innerTargetURI;
  1589. rv = originDocument->NodePrincipal()->GetURI(getter_AddRefs(originURI));
  1590. if (NS_SUCCEEDED(rv) && originURI) {
  1591. innerOriginURI = NS_GetInnermostURI(originURI);
  1592. }
  1593. rv = targetDocument->NodePrincipal()->GetURI(getter_AddRefs(targetURI));
  1594. if (NS_SUCCEEDED(rv) && targetURI) {
  1595. innerTargetURI = NS_GetInnermostURI(targetURI);
  1596. }
  1597. return innerOriginURI && innerTargetURI &&
  1598. NS_SUCCEEDED(innerOriginURI->SchemeIs("file", &originIsFile)) &&
  1599. NS_SUCCEEDED(innerTargetURI->SchemeIs("file", &targetIsFile)) &&
  1600. originIsFile && targetIsFile;
  1601. }
  1602. nsresult
  1603. nsDocShell::GetEldestPresContext(nsPresContext** aPresContext)
  1604. {
  1605. NS_ENSURE_ARG_POINTER(aPresContext);
  1606. *aPresContext = nullptr;
  1607. nsCOMPtr<nsIContentViewer> viewer = mContentViewer;
  1608. while (viewer) {
  1609. nsCOMPtr<nsIContentViewer> prevViewer;
  1610. viewer->GetPreviousViewer(getter_AddRefs(prevViewer));
  1611. if (!prevViewer) {
  1612. return viewer->GetPresContext(aPresContext);
  1613. }
  1614. viewer = prevViewer;
  1615. }
  1616. return NS_OK;
  1617. }
  1618. NS_IMETHODIMP
  1619. nsDocShell::GetPresContext(nsPresContext** aPresContext)
  1620. {
  1621. NS_ENSURE_ARG_POINTER(aPresContext);
  1622. *aPresContext = nullptr;
  1623. if (!mContentViewer) {
  1624. return NS_OK;
  1625. }
  1626. return mContentViewer->GetPresContext(aPresContext);
  1627. }
  1628. NS_IMETHODIMP_(nsIPresShell*)
  1629. nsDocShell::GetPresShell()
  1630. {
  1631. RefPtr<nsPresContext> presContext;
  1632. (void)GetPresContext(getter_AddRefs(presContext));
  1633. return presContext ? presContext->GetPresShell() : nullptr;
  1634. }
  1635. NS_IMETHODIMP
  1636. nsDocShell::GetEldestPresShell(nsIPresShell** aPresShell)
  1637. {
  1638. nsresult rv = NS_OK;
  1639. NS_ENSURE_ARG_POINTER(aPresShell);
  1640. *aPresShell = nullptr;
  1641. RefPtr<nsPresContext> presContext;
  1642. (void)GetEldestPresContext(getter_AddRefs(presContext));
  1643. if (presContext) {
  1644. NS_IF_ADDREF(*aPresShell = presContext->GetPresShell());
  1645. }
  1646. return rv;
  1647. }
  1648. NS_IMETHODIMP
  1649. nsDocShell::GetContentViewer(nsIContentViewer** aContentViewer)
  1650. {
  1651. NS_ENSURE_ARG_POINTER(aContentViewer);
  1652. *aContentViewer = mContentViewer;
  1653. NS_IF_ADDREF(*aContentViewer);
  1654. return NS_OK;
  1655. }
  1656. NS_IMETHODIMP
  1657. nsDocShell::SetChromeEventHandler(nsIDOMEventTarget* aChromeEventHandler)
  1658. {
  1659. // Weak reference. Don't addref.
  1660. nsCOMPtr<EventTarget> handler = do_QueryInterface(aChromeEventHandler);
  1661. mChromeEventHandler = handler.get();
  1662. if (mScriptGlobal) {
  1663. mScriptGlobal->SetChromeEventHandler(mChromeEventHandler);
  1664. }
  1665. return NS_OK;
  1666. }
  1667. NS_IMETHODIMP
  1668. nsDocShell::GetChromeEventHandler(nsIDOMEventTarget** aChromeEventHandler)
  1669. {
  1670. NS_ENSURE_ARG_POINTER(aChromeEventHandler);
  1671. nsCOMPtr<EventTarget> handler = mChromeEventHandler;
  1672. handler.forget(aChromeEventHandler);
  1673. return NS_OK;
  1674. }
  1675. NS_IMETHODIMP
  1676. nsDocShell::SetCurrentURI(nsIURI* aURI)
  1677. {
  1678. // Note that securityUI will set STATE_IS_INSECURE, even if
  1679. // the scheme of |aURI| is "https".
  1680. SetCurrentURI(aURI, nullptr, true, 0);
  1681. return NS_OK;
  1682. }
  1683. bool
  1684. nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
  1685. bool aFireOnLocationChange, uint32_t aLocationFlags)
  1686. {
  1687. if (gDocShellLeakLog && MOZ_LOG_TEST(gDocShellLeakLog, LogLevel::Debug)) {
  1688. PR_LogPrint("DOCSHELL %p SetCurrentURI %s\n",
  1689. this, aURI ? aURI->GetSpecOrDefault().get() : "");
  1690. }
  1691. // We don't want to send a location change when we're displaying an error
  1692. // page, and we don't want to change our idea of "current URI" either
  1693. if (mLoadType == LOAD_ERROR_PAGE) {
  1694. return false;
  1695. }
  1696. mCurrentURI = NS_TryToMakeImmutable(aURI);
  1697. if (!NS_IsAboutBlank(mCurrentURI)) {
  1698. mHasLoadedNonBlankURI = true;
  1699. }
  1700. bool isRoot = false; // Is this the root docshell
  1701. bool isSubFrame = false; // Is this a subframe navigation?
  1702. nsCOMPtr<nsIDocShellTreeItem> root;
  1703. GetSameTypeRootTreeItem(getter_AddRefs(root));
  1704. if (root.get() == static_cast<nsIDocShellTreeItem*>(this)) {
  1705. // This is the root docshell
  1706. isRoot = true;
  1707. }
  1708. if (mLSHE) {
  1709. mLSHE->GetIsSubFrame(&isSubFrame);
  1710. }
  1711. if (!isSubFrame && !isRoot) {
  1712. /*
  1713. * We don't want to send OnLocationChange notifications when
  1714. * a subframe is being loaded for the first time, while
  1715. * visiting a frameset page
  1716. */
  1717. return false;
  1718. }
  1719. if (aFireOnLocationChange) {
  1720. FireOnLocationChange(this, aRequest, aURI, aLocationFlags);
  1721. }
  1722. return !aFireOnLocationChange;
  1723. }
  1724. NS_IMETHODIMP
  1725. nsDocShell::GetCharset(nsACString& aCharset)
  1726. {
  1727. aCharset.Truncate();
  1728. nsIPresShell* presShell = GetPresShell();
  1729. NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
  1730. nsIDocument* doc = presShell->GetDocument();
  1731. NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
  1732. aCharset = doc->GetDocumentCharacterSet();
  1733. return NS_OK;
  1734. }
  1735. NS_IMETHODIMP
  1736. nsDocShell::GatherCharsetMenuTelemetry()
  1737. {
  1738. /* STUB */
  1739. return NS_OK;
  1740. }
  1741. NS_IMETHODIMP
  1742. nsDocShell::SetCharset(const nsACString& aCharset)
  1743. {
  1744. // set the charset override
  1745. return SetForcedCharset(aCharset);
  1746. }
  1747. NS_IMETHODIMP
  1748. nsDocShell::SetForcedCharset(const nsACString& aCharset)
  1749. {
  1750. if (aCharset.IsEmpty()) {
  1751. mForcedCharset.Truncate();
  1752. return NS_OK;
  1753. }
  1754. nsAutoCString encoding;
  1755. if (!EncodingUtils::FindEncodingForLabel(aCharset, encoding)) {
  1756. // Reject unknown labels
  1757. return NS_ERROR_INVALID_ARG;
  1758. }
  1759. if (!EncodingUtils::IsAsciiCompatible(encoding)) {
  1760. // Reject XSS hazards
  1761. return NS_ERROR_INVALID_ARG;
  1762. }
  1763. mForcedCharset = encoding;
  1764. return NS_OK;
  1765. }
  1766. NS_IMETHODIMP
  1767. nsDocShell::GetForcedCharset(nsACString& aResult)
  1768. {
  1769. aResult = mForcedCharset;
  1770. return NS_OK;
  1771. }
  1772. void
  1773. nsDocShell::SetParentCharset(const nsACString& aCharset,
  1774. int32_t aCharsetSource,
  1775. nsIPrincipal* aPrincipal)
  1776. {
  1777. mParentCharset = aCharset;
  1778. mParentCharsetSource = aCharsetSource;
  1779. mParentCharsetPrincipal = aPrincipal;
  1780. }
  1781. void
  1782. nsDocShell::GetParentCharset(nsACString& aCharset,
  1783. int32_t* aCharsetSource,
  1784. nsIPrincipal** aPrincipal)
  1785. {
  1786. aCharset = mParentCharset;
  1787. *aCharsetSource = mParentCharsetSource;
  1788. NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal);
  1789. }
  1790. NS_IMETHODIMP
  1791. nsDocShell::GetChannelIsUnsafe(bool* aUnsafe)
  1792. {
  1793. *aUnsafe = false;
  1794. nsIChannel* channel = GetCurrentDocChannel();
  1795. if (!channel) {
  1796. return NS_OK;
  1797. }
  1798. nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(channel);
  1799. if (!jarChannel) {
  1800. return NS_OK;
  1801. }
  1802. return jarChannel->GetIsUnsafe(aUnsafe);
  1803. }
  1804. NS_IMETHODIMP
  1805. nsDocShell::GetHasMixedActiveContentLoaded(bool* aHasMixedActiveContentLoaded)
  1806. {
  1807. nsCOMPtr<nsIDocument> doc(GetDocument());
  1808. *aHasMixedActiveContentLoaded = doc && doc->GetHasMixedActiveContentLoaded();
  1809. return NS_OK;
  1810. }
  1811. NS_IMETHODIMP
  1812. nsDocShell::GetHasMixedActiveContentBlocked(bool* aHasMixedActiveContentBlocked)
  1813. {
  1814. nsCOMPtr<nsIDocument> doc(GetDocument());
  1815. *aHasMixedActiveContentBlocked =
  1816. doc && doc->GetHasMixedActiveContentBlocked();
  1817. return NS_OK;
  1818. }
  1819. NS_IMETHODIMP
  1820. nsDocShell::GetHasMixedDisplayContentLoaded(bool* aHasMixedDisplayContentLoaded)
  1821. {
  1822. nsCOMPtr<nsIDocument> doc(GetDocument());
  1823. *aHasMixedDisplayContentLoaded =
  1824. doc && doc->GetHasMixedDisplayContentLoaded();
  1825. return NS_OK;
  1826. }
  1827. NS_IMETHODIMP
  1828. nsDocShell::GetHasMixedDisplayContentBlocked(
  1829. bool* aHasMixedDisplayContentBlocked)
  1830. {
  1831. nsCOMPtr<nsIDocument> doc(GetDocument());
  1832. *aHasMixedDisplayContentBlocked =
  1833. doc && doc->GetHasMixedDisplayContentBlocked();
  1834. return NS_OK;
  1835. }
  1836. NS_IMETHODIMP
  1837. nsDocShell::GetHasTrackingContentBlocked(bool* aHasTrackingContentBlocked)
  1838. {
  1839. nsCOMPtr<nsIDocument> doc(GetDocument());
  1840. *aHasTrackingContentBlocked = doc && doc->GetHasTrackingContentBlocked();
  1841. return NS_OK;
  1842. }
  1843. NS_IMETHODIMP
  1844. nsDocShell::GetHasTrackingContentLoaded(bool* aHasTrackingContentLoaded)
  1845. {
  1846. nsCOMPtr<nsIDocument> doc(GetDocument());
  1847. *aHasTrackingContentLoaded = doc && doc->GetHasTrackingContentLoaded();
  1848. return NS_OK;
  1849. }
  1850. NS_IMETHODIMP
  1851. nsDocShell::GetAllowPlugins(bool* aAllowPlugins)
  1852. {
  1853. NS_ENSURE_ARG_POINTER(aAllowPlugins);
  1854. *aAllowPlugins = mAllowPlugins;
  1855. if (!mAllowPlugins) {
  1856. return NS_OK;
  1857. }
  1858. bool unsafe;
  1859. *aAllowPlugins = NS_SUCCEEDED(GetChannelIsUnsafe(&unsafe)) && !unsafe;
  1860. return NS_OK;
  1861. }
  1862. NS_IMETHODIMP
  1863. nsDocShell::SetAllowPlugins(bool aAllowPlugins)
  1864. {
  1865. mAllowPlugins = aAllowPlugins;
  1866. // XXX should enable or disable a plugin host
  1867. return NS_OK;
  1868. }
  1869. NS_IMETHODIMP
  1870. nsDocShell::GetAllowJavascript(bool* aAllowJavascript)
  1871. {
  1872. NS_ENSURE_ARG_POINTER(aAllowJavascript);
  1873. *aAllowJavascript = mAllowJavascript;
  1874. return NS_OK;
  1875. }
  1876. NS_IMETHODIMP
  1877. nsDocShell::SetAllowJavascript(bool aAllowJavascript)
  1878. {
  1879. mAllowJavascript = aAllowJavascript;
  1880. RecomputeCanExecuteScripts();
  1881. return NS_OK;
  1882. }
  1883. NS_IMETHODIMP
  1884. nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing)
  1885. {
  1886. NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing);
  1887. AssertOriginAttributesMatchPrivateBrowsing();
  1888. *aUsePrivateBrowsing = mPrivateBrowsingId > 0;
  1889. return NS_OK;
  1890. }
  1891. NS_IMETHODIMP
  1892. nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing)
  1893. {
  1894. nsContentUtils::ReportToConsoleNonLocalized(
  1895. NS_LITERAL_STRING("Only internal code is allowed to set the usePrivateBrowsing attribute"),
  1896. nsIScriptError::warningFlag,
  1897. NS_LITERAL_CSTRING("Internal API Used"),
  1898. mContentViewer ? mContentViewer->GetDocument() : nullptr);
  1899. if (!CanSetOriginAttributes()) {
  1900. bool changed = aUsePrivateBrowsing != (mPrivateBrowsingId > 0);
  1901. return changed ? NS_ERROR_FAILURE : NS_OK;
  1902. }
  1903. return SetPrivateBrowsing(aUsePrivateBrowsing);
  1904. }
  1905. NS_IMETHODIMP
  1906. nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing)
  1907. {
  1908. bool changed = aUsePrivateBrowsing != (mPrivateBrowsingId > 0);
  1909. if (changed) {
  1910. mPrivateBrowsingId = aUsePrivateBrowsing ? 1 : 0;
  1911. if (mItemType != typeChrome) {
  1912. mOriginAttributes.SyncAttributesWithPrivateBrowsing(aUsePrivateBrowsing);
  1913. }
  1914. if (mAffectPrivateSessionLifetime) {
  1915. if (aUsePrivateBrowsing) {
  1916. IncreasePrivateDocShellCount();
  1917. } else {
  1918. DecreasePrivateDocShellCount();
  1919. }
  1920. }
  1921. }
  1922. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  1923. while (iter.HasMore()) {
  1924. nsCOMPtr<nsILoadContext> shell = do_QueryObject(iter.GetNext());
  1925. if (shell) {
  1926. shell->SetPrivateBrowsing(aUsePrivateBrowsing);
  1927. }
  1928. }
  1929. if (changed) {
  1930. nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers);
  1931. while (iter.HasMore()) {
  1932. nsWeakPtr ref = iter.GetNext();
  1933. nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref);
  1934. if (!obs) {
  1935. mPrivacyObservers.RemoveElement(ref);
  1936. } else {
  1937. obs->PrivateModeChanged(aUsePrivateBrowsing);
  1938. }
  1939. }
  1940. }
  1941. AssertOriginAttributesMatchPrivateBrowsing();
  1942. return NS_OK;
  1943. }
  1944. NS_IMETHODIMP
  1945. nsDocShell::GetHasLoadedNonBlankURI(bool* aResult)
  1946. {
  1947. NS_ENSURE_ARG_POINTER(aResult);
  1948. *aResult = mHasLoadedNonBlankURI;
  1949. return NS_OK;
  1950. }
  1951. NS_IMETHODIMP
  1952. nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs)
  1953. {
  1954. NS_ENSURE_ARG_POINTER(aUseRemoteTabs);
  1955. *aUseRemoteTabs = mUseRemoteTabs;
  1956. return NS_OK;
  1957. }
  1958. NS_IMETHODIMP
  1959. nsDocShell::SetRemoteTabs(bool aUseRemoteTabs)
  1960. {
  1961. mUseRemoteTabs = aUseRemoteTabs;
  1962. return NS_OK;
  1963. }
  1964. NS_IMETHODIMP
  1965. nsDocShell::SetAffectPrivateSessionLifetime(bool aAffectLifetime)
  1966. {
  1967. bool change = aAffectLifetime != mAffectPrivateSessionLifetime;
  1968. if (change && UsePrivateBrowsing()) {
  1969. AssertOriginAttributesMatchPrivateBrowsing();
  1970. if (aAffectLifetime) {
  1971. IncreasePrivateDocShellCount();
  1972. } else {
  1973. DecreasePrivateDocShellCount();
  1974. }
  1975. }
  1976. mAffectPrivateSessionLifetime = aAffectLifetime;
  1977. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  1978. while (iter.HasMore()) {
  1979. nsCOMPtr<nsIDocShell> shell = do_QueryObject(iter.GetNext());
  1980. if (shell) {
  1981. shell->SetAffectPrivateSessionLifetime(aAffectLifetime);
  1982. }
  1983. }
  1984. return NS_OK;
  1985. }
  1986. NS_IMETHODIMP
  1987. nsDocShell::GetAffectPrivateSessionLifetime(bool* aAffectLifetime)
  1988. {
  1989. *aAffectLifetime = mAffectPrivateSessionLifetime;
  1990. return NS_OK;
  1991. }
  1992. NS_IMETHODIMP
  1993. nsDocShell::AddWeakPrivacyTransitionObserver(
  1994. nsIPrivacyTransitionObserver* aObserver)
  1995. {
  1996. nsWeakPtr weakObs = do_GetWeakReference(aObserver);
  1997. if (!weakObs) {
  1998. return NS_ERROR_NOT_AVAILABLE;
  1999. }
  2000. return mPrivacyObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
  2001. }
  2002. NS_IMETHODIMP
  2003. nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver)
  2004. {
  2005. nsWeakPtr weakObs = do_GetWeakReference(aObserver);
  2006. if (!weakObs) {
  2007. return NS_ERROR_FAILURE;
  2008. }
  2009. return mReflowObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
  2010. }
  2011. NS_IMETHODIMP
  2012. nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver)
  2013. {
  2014. nsWeakPtr obs = do_GetWeakReference(aObserver);
  2015. return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
  2016. }
  2017. NS_IMETHODIMP
  2018. nsDocShell::NotifyReflowObservers(bool aInterruptible,
  2019. DOMHighResTimeStamp aStart,
  2020. DOMHighResTimeStamp aEnd)
  2021. {
  2022. nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers);
  2023. while (iter.HasMore()) {
  2024. nsWeakPtr ref = iter.GetNext();
  2025. nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref);
  2026. if (!obs) {
  2027. mReflowObservers.RemoveElement(ref);
  2028. } else if (aInterruptible) {
  2029. obs->ReflowInterruptible(aStart, aEnd);
  2030. } else {
  2031. obs->Reflow(aStart, aEnd);
  2032. }
  2033. }
  2034. return NS_OK;
  2035. }
  2036. NS_IMETHODIMP
  2037. nsDocShell::GetAllowMetaRedirects(bool* aReturn)
  2038. {
  2039. NS_ENSURE_ARG_POINTER(aReturn);
  2040. *aReturn = mAllowMetaRedirects;
  2041. if (!mAllowMetaRedirects) {
  2042. return NS_OK;
  2043. }
  2044. bool unsafe;
  2045. *aReturn = NS_SUCCEEDED(GetChannelIsUnsafe(&unsafe)) && !unsafe;
  2046. return NS_OK;
  2047. }
  2048. NS_IMETHODIMP
  2049. nsDocShell::SetAllowMetaRedirects(bool aValue)
  2050. {
  2051. mAllowMetaRedirects = aValue;
  2052. return NS_OK;
  2053. }
  2054. NS_IMETHODIMP
  2055. nsDocShell::GetAllowSubframes(bool* aAllowSubframes)
  2056. {
  2057. NS_ENSURE_ARG_POINTER(aAllowSubframes);
  2058. *aAllowSubframes = mAllowSubframes;
  2059. return NS_OK;
  2060. }
  2061. NS_IMETHODIMP
  2062. nsDocShell::SetAllowSubframes(bool aAllowSubframes)
  2063. {
  2064. mAllowSubframes = aAllowSubframes;
  2065. return NS_OK;
  2066. }
  2067. NS_IMETHODIMP
  2068. nsDocShell::GetAllowImages(bool* aAllowImages)
  2069. {
  2070. NS_ENSURE_ARG_POINTER(aAllowImages);
  2071. *aAllowImages = mAllowImages;
  2072. return NS_OK;
  2073. }
  2074. NS_IMETHODIMP
  2075. nsDocShell::SetAllowImages(bool aAllowImages)
  2076. {
  2077. mAllowImages = aAllowImages;
  2078. return NS_OK;
  2079. }
  2080. NS_IMETHODIMP
  2081. nsDocShell::GetAllowMedia(bool* aAllowMedia)
  2082. {
  2083. *aAllowMedia = mAllowMedia;
  2084. return NS_OK;
  2085. }
  2086. NS_IMETHODIMP
  2087. nsDocShell::SetAllowMedia(bool aAllowMedia)
  2088. {
  2089. mAllowMedia = aAllowMedia;
  2090. // Mute or unmute audio contexts attached to the inner window.
  2091. if (mScriptGlobal) {
  2092. if (nsPIDOMWindowInner* innerWin =
  2093. mScriptGlobal->AsOuter()->GetCurrentInnerWindow()) {
  2094. if (aAllowMedia) {
  2095. innerWin->UnmuteAudioContexts();
  2096. } else {
  2097. innerWin->MuteAudioContexts();
  2098. }
  2099. }
  2100. }
  2101. return NS_OK;
  2102. }
  2103. NS_IMETHODIMP
  2104. nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch)
  2105. {
  2106. *aAllowDNSPrefetch = mAllowDNSPrefetch;
  2107. return NS_OK;
  2108. }
  2109. NS_IMETHODIMP
  2110. nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch)
  2111. {
  2112. mAllowDNSPrefetch = aAllowDNSPrefetch;
  2113. return NS_OK;
  2114. }
  2115. NS_IMETHODIMP
  2116. nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl)
  2117. {
  2118. *aAllowWindowControl = mAllowWindowControl;
  2119. return NS_OK;
  2120. }
  2121. NS_IMETHODIMP
  2122. nsDocShell::SetAllowWindowControl(bool aAllowWindowControl)
  2123. {
  2124. mAllowWindowControl = aAllowWindowControl;
  2125. return NS_OK;
  2126. }
  2127. NS_IMETHODIMP
  2128. nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting)
  2129. {
  2130. *aAllowContentRetargeting = mAllowContentRetargeting;
  2131. return NS_OK;
  2132. }
  2133. NS_IMETHODIMP
  2134. nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting)
  2135. {
  2136. mAllowContentRetargetingOnChildren = aAllowContentRetargeting;
  2137. mAllowContentRetargeting = aAllowContentRetargeting;
  2138. return NS_OK;
  2139. }
  2140. NS_IMETHODIMP
  2141. nsDocShell::GetAllowContentRetargetingOnChildren(
  2142. bool* aAllowContentRetargetingOnChildren)
  2143. {
  2144. *aAllowContentRetargetingOnChildren = mAllowContentRetargetingOnChildren;
  2145. return NS_OK;
  2146. }
  2147. NS_IMETHODIMP
  2148. nsDocShell::SetAllowContentRetargetingOnChildren(
  2149. bool aAllowContentRetargetingOnChildren)
  2150. {
  2151. mAllowContentRetargetingOnChildren = aAllowContentRetargetingOnChildren;
  2152. return NS_OK;
  2153. }
  2154. NS_IMETHODIMP
  2155. nsDocShell::GetInheritPrivateBrowsingId(bool* aInheritPrivateBrowsingId)
  2156. {
  2157. *aInheritPrivateBrowsingId = mInheritPrivateBrowsingId;
  2158. return NS_OK;
  2159. }
  2160. NS_IMETHODIMP
  2161. nsDocShell::SetInheritPrivateBrowsingId(bool aInheritPrivateBrowsingId)
  2162. {
  2163. mInheritPrivateBrowsingId = aInheritPrivateBrowsingId;
  2164. return NS_OK;
  2165. }
  2166. NS_IMETHODIMP
  2167. nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
  2168. {
  2169. NS_ENSURE_ARG_POINTER(aFullscreenAllowed);
  2170. // Browsers and apps have their mFullscreenAllowed retrieved from their
  2171. // corresponding iframe in their parent upon creation.
  2172. if (mFullscreenAllowed != CHECK_ATTRIBUTES) {
  2173. *aFullscreenAllowed = (mFullscreenAllowed == PARENT_ALLOWS);
  2174. return NS_OK;
  2175. }
  2176. // Assume false until we determine otherwise...
  2177. *aFullscreenAllowed = false;
  2178. nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
  2179. if (!win) {
  2180. return NS_OK;
  2181. }
  2182. if (nsCOMPtr<Element> frameElement = win->GetFrameElementInternal()) {
  2183. if (frameElement->IsXULElement()) {
  2184. if (frameElement->HasAttr(kNameSpaceID_None,
  2185. nsGkAtoms::disablefullscreen)) {
  2186. // Document inside this frame is explicitly disabled.
  2187. return NS_OK;
  2188. }
  2189. } else {
  2190. // We do not allow document inside any containing element other
  2191. // than iframe to enter fullscreen.
  2192. if (frameElement->IsHTMLElement(nsGkAtoms::iframe)) {
  2193. // If any ancestor iframe does not have allowfullscreen attribute
  2194. // set, then fullscreen is not allowed.
  2195. if (!frameElement->HasAttr(kNameSpaceID_None,
  2196. nsGkAtoms::allowfullscreen) &&
  2197. !frameElement->HasAttr(kNameSpaceID_None,
  2198. nsGkAtoms::mozallowfullscreen)) {
  2199. return NS_OK;
  2200. }
  2201. } else if (frameElement->IsHTMLElement(nsGkAtoms::embed)) {
  2202. // Respect allowfullscreen only if this is a rewritten YouTube embed.
  2203. nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent =
  2204. do_QueryInterface(frameElement);
  2205. if (!objectLoadingContent) {
  2206. return NS_OK;
  2207. }
  2208. nsObjectLoadingContent* olc =
  2209. static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
  2210. if (!olc->IsRewrittenYoutubeEmbed()) {
  2211. return NS_OK;
  2212. }
  2213. // We don't have to check prefixed attributes because Flash does not
  2214. // support them.
  2215. if (!frameElement->HasAttr(kNameSpaceID_None,
  2216. nsGkAtoms::allowfullscreen)) {
  2217. return NS_OK;
  2218. }
  2219. } else {
  2220. // neither iframe nor embed
  2221. return NS_OK;
  2222. }
  2223. }
  2224. }
  2225. // If we have no parent then we're the root docshell; no ancestor of the
  2226. // original docshell doesn't have a allowfullscreen attribute, so
  2227. // report fullscreen as allowed.
  2228. RefPtr<nsDocShell> parent = GetParentDocshell();
  2229. if (!parent) {
  2230. *aFullscreenAllowed = true;
  2231. return NS_OK;
  2232. }
  2233. // Otherwise, we have a parent, continue the checking for
  2234. // mozFullscreenAllowed in the parent docshell's ancestors.
  2235. return parent->GetFullscreenAllowed(aFullscreenAllowed);
  2236. }
  2237. NS_IMETHODIMP
  2238. nsDocShell::SetFullscreenAllowed(bool aFullscreenAllowed)
  2239. {
  2240. if (!nsIDocShell::GetIsMozBrowserOrApp()) {
  2241. // Only allow setting of fullscreenAllowed on content/process boundaries.
  2242. // At non-boundaries the fullscreenAllowed attribute is calculated based on
  2243. // whether all enclosing frames have the "mozFullscreenAllowed" attribute
  2244. // set to "true". fullscreenAllowed is set at the process boundaries to
  2245. // propagate the value of the parent's "mozFullscreenAllowed" attribute
  2246. // across process boundaries.
  2247. return NS_ERROR_UNEXPECTED;
  2248. }
  2249. mFullscreenAllowed = (aFullscreenAllowed ? PARENT_ALLOWS : PARENT_PROHIBITS);
  2250. return NS_OK;
  2251. }
  2252. ScreenOrientationInternal
  2253. nsDocShell::OrientationLock()
  2254. {
  2255. return mOrientationLock;
  2256. }
  2257. void
  2258. nsDocShell::SetOrientationLock(ScreenOrientationInternal aOrientationLock)
  2259. {
  2260. mOrientationLock = aOrientationLock;
  2261. }
  2262. NS_IMETHODIMP
  2263. nsDocShell::GetMayEnableCharacterEncodingMenu(
  2264. bool* aMayEnableCharacterEncodingMenu)
  2265. {
  2266. *aMayEnableCharacterEncodingMenu = false;
  2267. if (!mContentViewer) {
  2268. return NS_OK;
  2269. }
  2270. nsIDocument* doc = mContentViewer->GetDocument();
  2271. if (!doc) {
  2272. return NS_OK;
  2273. }
  2274. if (doc->WillIgnoreCharsetOverride()) {
  2275. return NS_OK;
  2276. }
  2277. *aMayEnableCharacterEncodingMenu = true;
  2278. return NS_OK;
  2279. }
  2280. NS_IMETHODIMP
  2281. nsDocShell::GetDocShellEnumerator(int32_t aItemType, int32_t aDirection,
  2282. nsISimpleEnumerator** aResult)
  2283. {
  2284. NS_ENSURE_ARG_POINTER(aResult);
  2285. *aResult = nullptr;
  2286. RefPtr<nsDocShellEnumerator> docShellEnum;
  2287. if (aDirection == ENUMERATE_FORWARDS) {
  2288. docShellEnum = new nsDocShellForwardsEnumerator;
  2289. } else {
  2290. docShellEnum = new nsDocShellBackwardsEnumerator;
  2291. }
  2292. nsresult rv = docShellEnum->SetEnumDocShellType(aItemType);
  2293. if (NS_FAILED(rv)) {
  2294. return rv;
  2295. }
  2296. rv = docShellEnum->SetEnumerationRootItem((nsIDocShellTreeItem*)this);
  2297. if (NS_FAILED(rv)) {
  2298. return rv;
  2299. }
  2300. rv = docShellEnum->First();
  2301. if (NS_FAILED(rv)) {
  2302. return rv;
  2303. }
  2304. rv = docShellEnum->QueryInterface(NS_GET_IID(nsISimpleEnumerator),
  2305. (void**)aResult);
  2306. return rv;
  2307. }
  2308. NS_IMETHODIMP
  2309. nsDocShell::GetAppType(uint32_t* aAppType)
  2310. {
  2311. *aAppType = mAppType;
  2312. return NS_OK;
  2313. }
  2314. NS_IMETHODIMP
  2315. nsDocShell::SetAppType(uint32_t aAppType)
  2316. {
  2317. mAppType = aAppType;
  2318. return NS_OK;
  2319. }
  2320. NS_IMETHODIMP
  2321. nsDocShell::GetAllowAuth(bool* aAllowAuth)
  2322. {
  2323. *aAllowAuth = mAllowAuth;
  2324. return NS_OK;
  2325. }
  2326. NS_IMETHODIMP
  2327. nsDocShell::SetAllowAuth(bool aAllowAuth)
  2328. {
  2329. mAllowAuth = aAllowAuth;
  2330. return NS_OK;
  2331. }
  2332. NS_IMETHODIMP
  2333. nsDocShell::GetZoom(float* aZoom)
  2334. {
  2335. NS_ENSURE_ARG_POINTER(aZoom);
  2336. *aZoom = 1.0f;
  2337. return NS_OK;
  2338. }
  2339. NS_IMETHODIMP
  2340. nsDocShell::SetZoom(float aZoom)
  2341. {
  2342. return NS_ERROR_NOT_IMPLEMENTED;
  2343. }
  2344. NS_IMETHODIMP
  2345. nsDocShell::GetMarginWidth(int32_t* aWidth)
  2346. {
  2347. NS_ENSURE_ARG_POINTER(aWidth);
  2348. *aWidth = mMarginWidth;
  2349. return NS_OK;
  2350. }
  2351. NS_IMETHODIMP
  2352. nsDocShell::SetMarginWidth(int32_t aWidth)
  2353. {
  2354. mMarginWidth = aWidth;
  2355. return NS_OK;
  2356. }
  2357. NS_IMETHODIMP
  2358. nsDocShell::GetMarginHeight(int32_t* aHeight)
  2359. {
  2360. NS_ENSURE_ARG_POINTER(aHeight);
  2361. *aHeight = mMarginHeight;
  2362. return NS_OK;
  2363. }
  2364. NS_IMETHODIMP
  2365. nsDocShell::SetMarginHeight(int32_t aHeight)
  2366. {
  2367. mMarginHeight = aHeight;
  2368. return NS_OK;
  2369. }
  2370. NS_IMETHODIMP
  2371. nsDocShell::GetBusyFlags(uint32_t* aBusyFlags)
  2372. {
  2373. NS_ENSURE_ARG_POINTER(aBusyFlags);
  2374. *aBusyFlags = mBusyFlags;
  2375. return NS_OK;
  2376. }
  2377. NS_IMETHODIMP
  2378. nsDocShell::TabToTreeOwner(bool aForward, bool aForDocumentNavigation, bool* aTookFocus)
  2379. {
  2380. NS_ENSURE_ARG_POINTER(aTookFocus);
  2381. nsCOMPtr<nsIWebBrowserChromeFocus> chromeFocus = do_GetInterface(mTreeOwner);
  2382. if (chromeFocus) {
  2383. if (aForward) {
  2384. *aTookFocus = NS_SUCCEEDED(chromeFocus->FocusNextElement(aForDocumentNavigation));
  2385. } else {
  2386. *aTookFocus = NS_SUCCEEDED(chromeFocus->FocusPrevElement(aForDocumentNavigation));
  2387. }
  2388. } else {
  2389. *aTookFocus = false;
  2390. }
  2391. return NS_OK;
  2392. }
  2393. NS_IMETHODIMP
  2394. nsDocShell::GetSecurityUI(nsISecureBrowserUI** aSecurityUI)
  2395. {
  2396. NS_IF_ADDREF(*aSecurityUI = mSecurityUI);
  2397. return NS_OK;
  2398. }
  2399. NS_IMETHODIMP
  2400. nsDocShell::SetSecurityUI(nsISecureBrowserUI* aSecurityUI)
  2401. {
  2402. mSecurityUI = aSecurityUI;
  2403. mSecurityUI->SetDocShell(this);
  2404. return NS_OK;
  2405. }
  2406. NS_IMETHODIMP
  2407. nsDocShell::GetUseErrorPages(bool* aUseErrorPages)
  2408. {
  2409. *aUseErrorPages = UseErrorPages();
  2410. return NS_OK;
  2411. }
  2412. NS_IMETHODIMP
  2413. nsDocShell::SetUseErrorPages(bool aUseErrorPages)
  2414. {
  2415. // If mUseErrorPages is set explicitly, stop using sUseErrorPages.
  2416. if (mObserveErrorPages) {
  2417. mObserveErrorPages = false;
  2418. }
  2419. mUseErrorPages = aUseErrorPages;
  2420. return NS_OK;
  2421. }
  2422. NS_IMETHODIMP
  2423. nsDocShell::GetPreviousTransIndex(int32_t* aPreviousTransIndex)
  2424. {
  2425. *aPreviousTransIndex = mPreviousTransIndex;
  2426. return NS_OK;
  2427. }
  2428. NS_IMETHODIMP
  2429. nsDocShell::GetLoadedTransIndex(int32_t* aLoadedTransIndex)
  2430. {
  2431. *aLoadedTransIndex = mLoadedTransIndex;
  2432. return NS_OK;
  2433. }
  2434. NS_IMETHODIMP
  2435. nsDocShell::HistoryPurged(int32_t aNumEntries)
  2436. {
  2437. // These indices are used for fastback cache eviction, to determine
  2438. // which session history entries are candidates for content viewer
  2439. // eviction. We need to adjust by the number of entries that we
  2440. // just purged from history, so that we look at the right session history
  2441. // entries during eviction.
  2442. mPreviousTransIndex = std::max(-1, mPreviousTransIndex - aNumEntries);
  2443. mLoadedTransIndex = std::max(0, mLoadedTransIndex - aNumEntries);
  2444. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  2445. while (iter.HasMore()) {
  2446. nsCOMPtr<nsIDocShell> shell = do_QueryObject(iter.GetNext());
  2447. if (shell) {
  2448. shell->HistoryPurged(aNumEntries);
  2449. }
  2450. }
  2451. return NS_OK;
  2452. }
  2453. nsresult
  2454. nsDocShell::HistoryTransactionRemoved(int32_t aIndex)
  2455. {
  2456. // These indices are used for fastback cache eviction, to determine
  2457. // which session history entries are candidates for content viewer
  2458. // eviction. We need to adjust by the number of entries that we
  2459. // just purged from history, so that we look at the right session history
  2460. // entries during eviction.
  2461. if (aIndex == mPreviousTransIndex) {
  2462. mPreviousTransIndex = -1;
  2463. } else if (aIndex < mPreviousTransIndex) {
  2464. --mPreviousTransIndex;
  2465. }
  2466. if (mLoadedTransIndex == aIndex) {
  2467. mLoadedTransIndex = 0;
  2468. } else if (aIndex < mLoadedTransIndex) {
  2469. --mLoadedTransIndex;
  2470. }
  2471. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  2472. while (iter.HasMore()) {
  2473. nsCOMPtr<nsIDocShell> shell = do_QueryObject(iter.GetNext());
  2474. if (shell) {
  2475. static_cast<nsDocShell*>(shell.get())->HistoryTransactionRemoved(aIndex);
  2476. }
  2477. }
  2478. return NS_OK;
  2479. }
  2480. NS_IMETHODIMP
  2481. nsDocShell::SetRecordProfileTimelineMarkers(bool aValue)
  2482. {
  2483. bool currentValue = nsIDocShell::GetRecordProfileTimelineMarkers();
  2484. if (currentValue == aValue) {
  2485. return NS_OK;
  2486. }
  2487. RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
  2488. if (!timelines) {
  2489. return NS_OK;
  2490. }
  2491. if (aValue) {
  2492. MOZ_ASSERT(!timelines->HasConsumer(this));
  2493. timelines->AddConsumer(this);
  2494. MOZ_ASSERT(timelines->HasConsumer(this));
  2495. UseEntryScriptProfiling();
  2496. } else {
  2497. MOZ_ASSERT(timelines->HasConsumer(this));
  2498. timelines->RemoveConsumer(this);
  2499. MOZ_ASSERT(!timelines->HasConsumer(this));
  2500. UnuseEntryScriptProfiling();
  2501. }
  2502. return NS_OK;
  2503. }
  2504. NS_IMETHODIMP
  2505. nsDocShell::GetRecordProfileTimelineMarkers(bool* aValue)
  2506. {
  2507. *aValue = !!mObserved;
  2508. return NS_OK;
  2509. }
  2510. nsresult
  2511. nsDocShell::PopProfileTimelineMarkers(
  2512. JSContext* aCx,
  2513. JS::MutableHandle<JS::Value> aOut)
  2514. {
  2515. RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
  2516. if (!timelines) {
  2517. return NS_OK;
  2518. }
  2519. nsTArray<dom::ProfileTimelineMarker> store;
  2520. SequenceRooter<dom::ProfileTimelineMarker> rooter(aCx, &store);
  2521. timelines->PopMarkers(this, aCx, store);
  2522. if (!ToJSValue(aCx, store, aOut)) {
  2523. JS_ClearPendingException(aCx);
  2524. return NS_ERROR_UNEXPECTED;
  2525. }
  2526. return NS_OK;
  2527. }
  2528. nsresult
  2529. nsDocShell::Now(DOMHighResTimeStamp* aWhen)
  2530. {
  2531. bool ignore;
  2532. *aWhen =
  2533. (TimeStamp::Now() - TimeStamp::ProcessCreation(ignore)).ToMilliseconds();
  2534. return NS_OK;
  2535. }
  2536. NS_IMETHODIMP
  2537. nsDocShell::SetWindowDraggingAllowed(bool aValue)
  2538. {
  2539. RefPtr<nsDocShell> parent = GetParentDocshell();
  2540. if (!aValue && mItemType == typeChrome && !parent) {
  2541. // Window dragging is always allowed for top level
  2542. // chrome docshells.
  2543. return NS_ERROR_FAILURE;
  2544. }
  2545. mWindowDraggingAllowed = aValue;
  2546. return NS_OK;
  2547. }
  2548. NS_IMETHODIMP
  2549. nsDocShell::GetWindowDraggingAllowed(bool* aValue)
  2550. {
  2551. // window dragging regions in CSS (-moz-window-drag:drag)
  2552. // can be slow. Default behavior is to only allow it for
  2553. // chrome top level windows.
  2554. RefPtr<nsDocShell> parent = GetParentDocshell();
  2555. if (mItemType == typeChrome && !parent) {
  2556. // Top level chrome window
  2557. *aValue = true;
  2558. } else {
  2559. *aValue = mWindowDraggingAllowed;
  2560. }
  2561. return NS_OK;
  2562. }
  2563. nsIDOMStorageManager*
  2564. nsDocShell::TopSessionStorageManager()
  2565. {
  2566. nsresult rv;
  2567. nsCOMPtr<nsIDocShellTreeItem> topItem;
  2568. rv = GetSameTypeRootTreeItem(getter_AddRefs(topItem));
  2569. if (NS_FAILED(rv)) {
  2570. return nullptr;
  2571. }
  2572. if (!topItem) {
  2573. return nullptr;
  2574. }
  2575. nsDocShell* topDocShell = static_cast<nsDocShell*>(topItem.get());
  2576. if (topDocShell != this) {
  2577. return topDocShell->TopSessionStorageManager();
  2578. }
  2579. if (!mSessionStorageManager) {
  2580. mSessionStorageManager =
  2581. do_CreateInstance("@mozilla.org/dom/sessionStorage-manager;1");
  2582. }
  2583. return mSessionStorageManager;
  2584. }
  2585. NS_IMETHODIMP
  2586. nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
  2587. const nsAString& aDocumentURI,
  2588. bool aCreate,
  2589. nsIDOMStorage** aStorage)
  2590. {
  2591. nsCOMPtr<nsIDOMStorageManager> manager = TopSessionStorageManager();
  2592. if (!manager) {
  2593. return NS_ERROR_UNEXPECTED;
  2594. }
  2595. nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow();
  2596. AssertOriginAttributesMatchPrivateBrowsing();
  2597. if (aCreate) {
  2598. return manager->CreateStorage(domWin->GetCurrentInnerWindow(), aPrincipal,
  2599. aDocumentURI, UsePrivateBrowsing(), aStorage);
  2600. }
  2601. return manager->GetStorage(domWin->GetCurrentInnerWindow(), aPrincipal,
  2602. UsePrivateBrowsing(), aStorage);
  2603. }
  2604. nsresult
  2605. nsDocShell::AddSessionStorage(nsIPrincipal* aPrincipal, nsIDOMStorage* aStorage)
  2606. {
  2607. RefPtr<DOMStorage> storage = static_cast<DOMStorage*>(aStorage);
  2608. if (!storage) {
  2609. return NS_ERROR_UNEXPECTED;
  2610. }
  2611. nsIPrincipal* storagePrincipal = storage->GetPrincipal();
  2612. if (storagePrincipal != aPrincipal) {
  2613. NS_ERROR("Wanting to add a sessionStorage for different principal");
  2614. return NS_ERROR_DOM_SECURITY_ERR;
  2615. }
  2616. nsCOMPtr<nsIDOMStorageManager> manager = TopSessionStorageManager();
  2617. if (!manager) {
  2618. return NS_ERROR_UNEXPECTED;
  2619. }
  2620. return manager->CloneStorage(aStorage);
  2621. }
  2622. NS_IMETHODIMP
  2623. nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult)
  2624. {
  2625. NS_IF_ADDREF(*aResult = GetCurrentDocChannel());
  2626. return NS_OK;
  2627. }
  2628. nsIChannel*
  2629. nsDocShell::GetCurrentDocChannel()
  2630. {
  2631. if (mContentViewer) {
  2632. nsIDocument* doc = mContentViewer->GetDocument();
  2633. if (doc) {
  2634. return doc->GetChannel();
  2635. }
  2636. }
  2637. return nullptr;
  2638. }
  2639. NS_IMETHODIMP
  2640. nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver)
  2641. {
  2642. nsWeakPtr weakObs = do_GetWeakReference(aObserver);
  2643. if (!weakObs) {
  2644. return NS_ERROR_FAILURE;
  2645. }
  2646. return mScrollObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
  2647. }
  2648. NS_IMETHODIMP
  2649. nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver)
  2650. {
  2651. nsWeakPtr obs = do_GetWeakReference(aObserver);
  2652. return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
  2653. }
  2654. void
  2655. nsDocShell::NotifyAsyncPanZoomStarted()
  2656. {
  2657. nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
  2658. while (iter.HasMore()) {
  2659. nsWeakPtr ref = iter.GetNext();
  2660. nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
  2661. if (obs) {
  2662. obs->AsyncPanZoomStarted();
  2663. } else {
  2664. mScrollObservers.RemoveElement(ref);
  2665. }
  2666. }
  2667. }
  2668. void
  2669. nsDocShell::NotifyAsyncPanZoomStopped()
  2670. {
  2671. nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
  2672. while (iter.HasMore()) {
  2673. nsWeakPtr ref = iter.GetNext();
  2674. nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
  2675. if (obs) {
  2676. obs->AsyncPanZoomStopped();
  2677. } else {
  2678. mScrollObservers.RemoveElement(ref);
  2679. }
  2680. }
  2681. }
  2682. NS_IMETHODIMP
  2683. nsDocShell::NotifyScrollObservers()
  2684. {
  2685. nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
  2686. while (iter.HasMore()) {
  2687. nsWeakPtr ref = iter.GetNext();
  2688. nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
  2689. if (obs) {
  2690. obs->ScrollPositionChanged();
  2691. } else {
  2692. mScrollObservers.RemoveElement(ref);
  2693. }
  2694. }
  2695. return NS_OK;
  2696. }
  2697. //*****************************************************************************
  2698. // nsDocShell::nsIDocShellTreeItem
  2699. //*****************************************************************************
  2700. NS_IMETHODIMP
  2701. nsDocShell::GetName(nsAString& aName)
  2702. {
  2703. aName = mName;
  2704. return NS_OK;
  2705. }
  2706. NS_IMETHODIMP
  2707. nsDocShell::SetName(const nsAString& aName)
  2708. {
  2709. mName = aName;
  2710. return NS_OK;
  2711. }
  2712. NS_IMETHODIMP
  2713. nsDocShell::NameEquals(const nsAString& aName, bool* aResult)
  2714. {
  2715. NS_ENSURE_ARG_POINTER(aResult);
  2716. *aResult = mName.Equals(aName);
  2717. return NS_OK;
  2718. }
  2719. NS_IMETHODIMP
  2720. nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent)
  2721. {
  2722. aCustomUserAgent = mCustomUserAgent;
  2723. return NS_OK;
  2724. }
  2725. NS_IMETHODIMP
  2726. nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent)
  2727. {
  2728. mCustomUserAgent = aCustomUserAgent;
  2729. RefPtr<nsGlobalWindow> win = mScriptGlobal ?
  2730. mScriptGlobal->GetCurrentInnerWindowInternal() : nullptr;
  2731. if (win) {
  2732. ErrorResult ignored;
  2733. Navigator* navigator = win->GetNavigator(ignored);
  2734. ignored.SuppressException();
  2735. if (navigator) {
  2736. navigator->ClearUserAgentCache();
  2737. }
  2738. }
  2739. uint32_t childCount = mChildList.Length();
  2740. for (uint32_t i = 0; i < childCount; ++i) {
  2741. nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(ChildAt(i));
  2742. if (childShell) {
  2743. childShell->SetCustomUserAgent(aCustomUserAgent);
  2744. }
  2745. }
  2746. return NS_OK;
  2747. }
  2748. NS_IMETHODIMP
  2749. nsDocShell::GetTouchEventsOverride(uint32_t* aTouchEventsOverride)
  2750. {
  2751. NS_ENSURE_ARG_POINTER(aTouchEventsOverride);
  2752. *aTouchEventsOverride = mTouchEventsOverride;
  2753. return NS_OK;
  2754. }
  2755. NS_IMETHODIMP
  2756. nsDocShell::SetTouchEventsOverride(uint32_t aTouchEventsOverride)
  2757. {
  2758. if (!(aTouchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE ||
  2759. aTouchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED ||
  2760. aTouchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_DISABLED)) {
  2761. return NS_ERROR_INVALID_ARG;
  2762. }
  2763. mTouchEventsOverride = aTouchEventsOverride;
  2764. uint32_t childCount = mChildList.Length();
  2765. for (uint32_t i = 0; i < childCount; ++i) {
  2766. nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(ChildAt(i));
  2767. if (childShell) {
  2768. childShell->SetTouchEventsOverride(aTouchEventsOverride);
  2769. }
  2770. }
  2771. return NS_OK;
  2772. }
  2773. /* virtual */ int32_t
  2774. nsDocShell::ItemType()
  2775. {
  2776. return mItemType;
  2777. }
  2778. NS_IMETHODIMP
  2779. nsDocShell::GetItemType(int32_t* aItemType)
  2780. {
  2781. NS_ENSURE_ARG_POINTER(aItemType);
  2782. *aItemType = ItemType();
  2783. return NS_OK;
  2784. }
  2785. NS_IMETHODIMP
  2786. nsDocShell::SetItemType(int32_t aItemType)
  2787. {
  2788. NS_ENSURE_ARG((aItemType == typeChrome) || (typeContent == aItemType));
  2789. // Only allow setting the type on root docshells. Those would be the ones
  2790. // that have the docloader service as mParent or have no mParent at all.
  2791. nsCOMPtr<nsIDocumentLoader> docLoaderService =
  2792. do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
  2793. NS_ENSURE_TRUE(docLoaderService, NS_ERROR_UNEXPECTED);
  2794. NS_ENSURE_STATE(!mParent || mParent == docLoaderService);
  2795. mItemType = aItemType;
  2796. // disable auth prompting for anything but content
  2797. mAllowAuth = mItemType == typeContent;
  2798. RefPtr<nsPresContext> presContext = nullptr;
  2799. GetPresContext(getter_AddRefs(presContext));
  2800. if (presContext) {
  2801. presContext->UpdateIsChrome();
  2802. }
  2803. return NS_OK;
  2804. }
  2805. NS_IMETHODIMP
  2806. nsDocShell::GetParent(nsIDocShellTreeItem** aParent)
  2807. {
  2808. if (!mParent) {
  2809. *aParent = nullptr;
  2810. } else {
  2811. CallQueryInterface(mParent, aParent);
  2812. }
  2813. // Note that in the case when the parent is not an nsIDocShellTreeItem we
  2814. // don't want to throw; we just want to return null.
  2815. return NS_OK;
  2816. }
  2817. already_AddRefed<nsDocShell>
  2818. nsDocShell::GetParentDocshell()
  2819. {
  2820. nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent));
  2821. return docshell.forget().downcast<nsDocShell>();
  2822. }
  2823. void
  2824. nsDocShell::RecomputeCanExecuteScripts()
  2825. {
  2826. bool old = mCanExecuteScripts;
  2827. RefPtr<nsDocShell> parent = GetParentDocshell();
  2828. // If we have no tree owner, that means that we've been detached from the
  2829. // docshell tree (this is distinct from having no parent dochshell, which
  2830. // is the case for root docshells). It would be nice to simply disallow
  2831. // script in detached docshells, but bug 986542 demonstrates that this
  2832. // behavior breaks at least one website.
  2833. //
  2834. // So instead, we use our previous value, unless mAllowJavascript has been
  2835. // explicitly set to false.
  2836. if (!mTreeOwner) {
  2837. mCanExecuteScripts = mCanExecuteScripts && mAllowJavascript;
  2838. // If scripting has been explicitly disabled on our docshell, we're done.
  2839. } else if (!mAllowJavascript) {
  2840. mCanExecuteScripts = false;
  2841. // If we have a parent, inherit.
  2842. } else if (parent) {
  2843. mCanExecuteScripts = parent->mCanExecuteScripts;
  2844. // Otherwise, we're the root of the tree, and we haven't explicitly disabled
  2845. // script. Allow.
  2846. } else {
  2847. mCanExecuteScripts = true;
  2848. }
  2849. // Inform our active DOM window.
  2850. //
  2851. // This will pass the outer, which will be in the scope of the active inner.
  2852. if (mScriptGlobal && mScriptGlobal->GetGlobalJSObject()) {
  2853. xpc::Scriptability& scriptability =
  2854. xpc::Scriptability::Get(mScriptGlobal->GetGlobalJSObject());
  2855. scriptability.SetDocShellAllowsScript(mCanExecuteScripts);
  2856. }
  2857. // If our value has changed, our children might be affected. Recompute their
  2858. // value as well.
  2859. if (old != mCanExecuteScripts) {
  2860. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  2861. while (iter.HasMore()) {
  2862. static_cast<nsDocShell*>(iter.GetNext())->RecomputeCanExecuteScripts();
  2863. }
  2864. }
  2865. }
  2866. nsresult
  2867. nsDocShell::SetDocLoaderParent(nsDocLoader* aParent)
  2868. {
  2869. bool wasFrame = IsFrame();
  2870. #ifdef DEBUG
  2871. bool wasPrivate = UsePrivateBrowsing();
  2872. #endif
  2873. nsresult rv = nsDocLoader::SetDocLoaderParent(aParent);
  2874. NS_ENSURE_SUCCESS(rv, rv);
  2875. nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup);
  2876. if (wasFrame != IsFrame() && priorityGroup) {
  2877. priorityGroup->AdjustPriority(wasFrame ? -1 : 1);
  2878. }
  2879. // Curse ambiguous nsISupports inheritance!
  2880. nsISupports* parent = GetAsSupports(aParent);
  2881. // If parent is another docshell, we inherit all their flags for
  2882. // allowing plugins, scripting etc.
  2883. bool value;
  2884. nsString customUserAgent;
  2885. nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent));
  2886. if (parentAsDocShell) {
  2887. if (mAllowPlugins && NS_SUCCEEDED(parentAsDocShell->GetAllowPlugins(&value))) {
  2888. SetAllowPlugins(value);
  2889. }
  2890. if (mAllowJavascript && NS_SUCCEEDED(parentAsDocShell->GetAllowJavascript(&value))) {
  2891. SetAllowJavascript(value);
  2892. }
  2893. if (mAllowMetaRedirects && NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))) {
  2894. SetAllowMetaRedirects(value);
  2895. }
  2896. if (mAllowSubframes && NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))) {
  2897. SetAllowSubframes(value);
  2898. }
  2899. if (mAllowImages && NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))) {
  2900. SetAllowImages(value);
  2901. }
  2902. SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia);
  2903. if (mAllowWindowControl && NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))) {
  2904. SetAllowWindowControl(value);
  2905. }
  2906. SetAllowContentRetargeting(mAllowContentRetargeting &&
  2907. parentAsDocShell->GetAllowContentRetargetingOnChildren());
  2908. if (parentAsDocShell->GetIsPrerendered()) {
  2909. SetIsPrerendered();
  2910. }
  2911. if (NS_SUCCEEDED(parentAsDocShell->GetIsActive(&value))) {
  2912. // a prerendered docshell is not active yet
  2913. SetIsActive(value && !mIsPrerendered);
  2914. }
  2915. if (NS_SUCCEEDED(parentAsDocShell->GetCustomUserAgent(customUserAgent)) &&
  2916. !customUserAgent.IsEmpty()) {
  2917. SetCustomUserAgent(customUserAgent);
  2918. }
  2919. if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))) {
  2920. value = false;
  2921. }
  2922. SetAllowDNSPrefetch(mAllowDNSPrefetch && value);
  2923. if (mInheritPrivateBrowsingId) {
  2924. value = parentAsDocShell->GetAffectPrivateSessionLifetime();
  2925. SetAffectPrivateSessionLifetime(value);
  2926. }
  2927. uint32_t flags;
  2928. if (NS_SUCCEEDED(parentAsDocShell->GetDefaultLoadFlags(&flags))) {
  2929. SetDefaultLoadFlags(flags);
  2930. }
  2931. uint32_t touchEventsOverride;
  2932. if (NS_SUCCEEDED(parentAsDocShell->GetTouchEventsOverride(&touchEventsOverride))) {
  2933. SetTouchEventsOverride(touchEventsOverride);
  2934. }
  2935. }
  2936. nsCOMPtr<nsILoadContext> parentAsLoadContext(do_QueryInterface(parent));
  2937. if (parentAsLoadContext && mInheritPrivateBrowsingId &&
  2938. NS_SUCCEEDED(parentAsLoadContext->GetUsePrivateBrowsing(&value))) {
  2939. SetPrivateBrowsing(value);
  2940. }
  2941. nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent));
  2942. if (parentURIListener) {
  2943. mContentListener->SetParentContentListener(parentURIListener);
  2944. }
  2945. // Our parent has changed. Recompute scriptability.
  2946. RecomputeCanExecuteScripts();
  2947. NS_ASSERTION(mInheritPrivateBrowsingId || wasPrivate == UsePrivateBrowsing(),
  2948. "Private browsing state changed while inheritance was disabled");
  2949. return NS_OK;
  2950. }
  2951. NS_IMETHODIMP
  2952. nsDocShell::GetSameTypeParent(nsIDocShellTreeItem** aParent)
  2953. {
  2954. NS_ENSURE_ARG_POINTER(aParent);
  2955. *aParent = nullptr;
  2956. if (nsIDocShell::GetIsMozBrowserOrApp()) {
  2957. return NS_OK;
  2958. }
  2959. nsCOMPtr<nsIDocShellTreeItem> parent =
  2960. do_QueryInterface(GetAsSupports(mParent));
  2961. if (!parent) {
  2962. return NS_OK;
  2963. }
  2964. if (parent->ItemType() == mItemType) {
  2965. parent.swap(*aParent);
  2966. }
  2967. return NS_OK;
  2968. }
  2969. NS_IMETHODIMP
  2970. nsDocShell::GetSameTypeParentIgnoreBrowserAndAppBoundaries(nsIDocShell** aParent)
  2971. {
  2972. NS_ENSURE_ARG_POINTER(aParent);
  2973. *aParent = nullptr;
  2974. nsCOMPtr<nsIDocShellTreeItem> parent =
  2975. do_QueryInterface(GetAsSupports(mParent));
  2976. if (!parent) {
  2977. return NS_OK;
  2978. }
  2979. if (parent->ItemType() == mItemType) {
  2980. nsCOMPtr<nsIDocShell> parentDS = do_QueryInterface(parent);
  2981. parentDS.forget(aParent);
  2982. }
  2983. return NS_OK;
  2984. }
  2985. NS_IMETHODIMP
  2986. nsDocShell::GetRootTreeItem(nsIDocShellTreeItem** aRootTreeItem)
  2987. {
  2988. NS_ENSURE_ARG_POINTER(aRootTreeItem);
  2989. RefPtr<nsDocShell> root = this;
  2990. RefPtr<nsDocShell> parent = root->GetParentDocshell();
  2991. while (parent) {
  2992. root = parent;
  2993. parent = root->GetParentDocshell();
  2994. }
  2995. root.forget(aRootTreeItem);
  2996. return NS_OK;
  2997. }
  2998. NS_IMETHODIMP
  2999. nsDocShell::GetSameTypeRootTreeItem(nsIDocShellTreeItem** aRootTreeItem)
  3000. {
  3001. NS_ENSURE_ARG_POINTER(aRootTreeItem);
  3002. *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
  3003. nsCOMPtr<nsIDocShellTreeItem> parent;
  3004. NS_ENSURE_SUCCESS(GetSameTypeParent(getter_AddRefs(parent)),
  3005. NS_ERROR_FAILURE);
  3006. while (parent) {
  3007. *aRootTreeItem = parent;
  3008. NS_ENSURE_SUCCESS(
  3009. (*aRootTreeItem)->GetSameTypeParent(getter_AddRefs(parent)),
  3010. NS_ERROR_FAILURE);
  3011. }
  3012. NS_ADDREF(*aRootTreeItem);
  3013. return NS_OK;
  3014. }
  3015. NS_IMETHODIMP
  3016. nsDocShell::GetSameTypeRootTreeItemIgnoreBrowserAndAppBoundaries(nsIDocShell ** aRootTreeItem)
  3017. {
  3018. NS_ENSURE_ARG_POINTER(aRootTreeItem);
  3019. *aRootTreeItem = static_cast<nsIDocShell *>(this);
  3020. nsCOMPtr<nsIDocShell> parent;
  3021. NS_ENSURE_SUCCESS(GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent)),
  3022. NS_ERROR_FAILURE);
  3023. while (parent) {
  3024. *aRootTreeItem = parent;
  3025. NS_ENSURE_SUCCESS((*aRootTreeItem)->
  3026. GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent)),
  3027. NS_ERROR_FAILURE);
  3028. }
  3029. NS_ADDREF(*aRootTreeItem);
  3030. return NS_OK;
  3031. }
  3032. /* static */
  3033. bool
  3034. nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem,
  3035. nsIDocShellTreeItem* aAccessingItem,
  3036. bool aConsiderOpener)
  3037. {
  3038. NS_PRECONDITION(aTargetItem, "Must have target item!");
  3039. if (!gValidateOrigin || !aAccessingItem) {
  3040. // Good to go
  3041. return true;
  3042. }
  3043. // XXXbz should we care if aAccessingItem or the document therein is
  3044. // chrome? Should those get extra privileges?
  3045. // For historical context, see:
  3046. //
  3047. // Bug 13871: Prevent frameset spoofing
  3048. // Bug 103638: Targets with same name in different windows open in wrong
  3049. // window with javascript
  3050. // Bug 408052: Adopt "ancestor" frame navigation policy
  3051. // Now do a security check.
  3052. //
  3053. // Disallow navigation if the two frames are not part of the same app, or if
  3054. // they have different is-in-browser-element states.
  3055. //
  3056. // Allow navigation if
  3057. // 1) aAccessingItem can script aTargetItem or one of its ancestors in
  3058. // the frame hierarchy or
  3059. // 2) aTargetItem is a top-level frame and aAccessingItem is its descendant
  3060. // 3) aTargetItem is a top-level frame and aAccessingItem can target
  3061. // its opener per rule (1) or (2).
  3062. if (aTargetItem == aAccessingItem) {
  3063. // A frame is allowed to navigate itself.
  3064. return true;
  3065. }
  3066. nsCOMPtr<nsIDocShell> targetDS = do_QueryInterface(aTargetItem);
  3067. nsCOMPtr<nsIDocShell> accessingDS = do_QueryInterface(aAccessingItem);
  3068. if (!targetDS || !accessingDS) {
  3069. // We must be able to convert both to nsIDocShell.
  3070. return false;
  3071. }
  3072. if (targetDS->GetIsInIsolatedMozBrowserElement() !=
  3073. accessingDS->GetIsInIsolatedMozBrowserElement() ||
  3074. targetDS->GetAppId() != accessingDS->GetAppId()) {
  3075. return false;
  3076. }
  3077. nsCOMPtr<nsIDocShellTreeItem> accessingRoot;
  3078. aAccessingItem->GetSameTypeRootTreeItem(getter_AddRefs(accessingRoot));
  3079. nsCOMPtr<nsIDocShell> accessingRootDS = do_QueryInterface(accessingRoot);
  3080. nsCOMPtr<nsIDocShellTreeItem> targetRoot;
  3081. aTargetItem->GetSameTypeRootTreeItem(getter_AddRefs(targetRoot));
  3082. nsCOMPtr<nsIDocShell> targetRootDS = do_QueryInterface(targetRoot);
  3083. DocShellOriginAttributes targetOA =
  3084. static_cast<nsDocShell*>(targetDS.get())->GetOriginAttributes();
  3085. DocShellOriginAttributes accessingOA =
  3086. static_cast<nsDocShell*>(accessingDS.get())->GetOriginAttributes();
  3087. // When the first party isolation is on, the top-level docShell may not have
  3088. // the firstPartyDomain in its originAttributes, but its document will have
  3089. // it. So we get the firstPartyDomain from the nodePrincipal of the document
  3090. // before we compare the originAttributes.
  3091. if (OriginAttributes::IsFirstPartyEnabled()) {
  3092. if (accessingDS == accessingRootDS &&
  3093. aAccessingItem->ItemType() == nsIDocShellTreeItem::typeContent &&
  3094. !accessingDS->GetIsMozBrowserOrApp()) {
  3095. nsCOMPtr<nsIDocument> accessingDoc = aAccessingItem->GetDocument();
  3096. if (accessingDoc) {
  3097. nsCOMPtr<nsIPrincipal> accessingPrincipal = accessingDoc->NodePrincipal();
  3098. accessingOA.mFirstPartyDomain =
  3099. BasePrincipal::Cast(accessingPrincipal)->OriginAttributesRef().mFirstPartyDomain;
  3100. }
  3101. }
  3102. if (targetDS == targetRootDS &&
  3103. aTargetItem->ItemType() == nsIDocShellTreeItem::typeContent &&
  3104. !targetDS->GetIsMozBrowserOrApp()) {
  3105. nsCOMPtr<nsIDocument> targetDoc = aAccessingItem->GetDocument();
  3106. if (targetDoc) {
  3107. nsCOMPtr<nsIPrincipal> targetPrincipal = targetDoc->NodePrincipal();
  3108. targetOA.mFirstPartyDomain =
  3109. BasePrincipal::Cast(targetPrincipal)->OriginAttributesRef().mFirstPartyDomain;
  3110. }
  3111. }
  3112. }
  3113. if (targetOA != accessingOA) {
  3114. return false;
  3115. }
  3116. // A private document can't access a non-private one, and vice versa.
  3117. if (static_cast<nsDocShell*>(targetDS.get())->UsePrivateBrowsing() !=
  3118. static_cast<nsDocShell*>(accessingDS.get())->UsePrivateBrowsing()) {
  3119. return false;
  3120. }
  3121. if (aTargetItem == accessingRoot) {
  3122. // A frame can navigate its root.
  3123. return true;
  3124. }
  3125. // Check if aAccessingItem can navigate one of aTargetItem's ancestors.
  3126. nsCOMPtr<nsIDocShellTreeItem> target = aTargetItem;
  3127. do {
  3128. if (ValidateOrigin(aAccessingItem, target)) {
  3129. return true;
  3130. }
  3131. nsCOMPtr<nsIDocShellTreeItem> parent;
  3132. target->GetSameTypeParent(getter_AddRefs(parent));
  3133. parent.swap(target);
  3134. } while (target);
  3135. if (aTargetItem != targetRoot) {
  3136. // target is a subframe, not in accessor's frame hierarchy, and all its
  3137. // ancestors have origins different from that of the accessor. Don't
  3138. // allow access.
  3139. return false;
  3140. }
  3141. if (!aConsiderOpener) {
  3142. // All done here
  3143. return false;
  3144. }
  3145. nsCOMPtr<nsPIDOMWindowOuter> targetWindow = aTargetItem->GetWindow();
  3146. if (!targetWindow) {
  3147. NS_ERROR("This should not happen, really");
  3148. return false;
  3149. }
  3150. nsCOMPtr<mozIDOMWindowProxy> targetOpener = targetWindow->GetOpener();
  3151. nsCOMPtr<nsIWebNavigation> openerWebNav(do_GetInterface(targetOpener));
  3152. nsCOMPtr<nsIDocShellTreeItem> openerItem(do_QueryInterface(openerWebNav));
  3153. if (!openerItem) {
  3154. return false;
  3155. }
  3156. return CanAccessItem(openerItem, aAccessingItem, false);
  3157. }
  3158. static bool
  3159. ItemIsActive(nsIDocShellTreeItem* aItem)
  3160. {
  3161. if (nsCOMPtr<nsPIDOMWindowOuter> window = aItem->GetWindow()) {
  3162. auto* win = nsGlobalWindow::Cast(window);
  3163. MOZ_ASSERT(win->IsOuterWindow());
  3164. if (!win->GetClosedOuter()) {
  3165. return true;
  3166. }
  3167. }
  3168. return false;
  3169. }
  3170. NS_IMETHODIMP
  3171. nsDocShell::FindItemWithName(const nsAString& aName,
  3172. nsISupports* aRequestor,
  3173. nsIDocShellTreeItem* aOriginalRequestor,
  3174. nsIDocShellTreeItem** aResult)
  3175. {
  3176. NS_ENSURE_ARG_POINTER(aResult);
  3177. // If we don't find one, we return NS_OK and a null result
  3178. *aResult = nullptr;
  3179. if (aName.IsEmpty()) {
  3180. return NS_OK;
  3181. }
  3182. if (aRequestor) {
  3183. // If aRequestor is not null we don't need to check special names, so
  3184. // just hand straight off to the search by actual name function.
  3185. return DoFindItemWithName(aName, aRequestor, aOriginalRequestor, aResult);
  3186. } else {
  3187. // This is the entry point into the target-finding algorithm. Check
  3188. // for special names. This should only be done once, hence the check
  3189. // for a null aRequestor.
  3190. nsCOMPtr<nsIDocShellTreeItem> foundItem;
  3191. if (aName.LowerCaseEqualsLiteral("_self")) {
  3192. foundItem = this;
  3193. } else if (aName.LowerCaseEqualsLiteral("_blank")) {
  3194. // Just return null. Caller must handle creating a new window with
  3195. // a blank name himself.
  3196. return NS_OK;
  3197. } else if (aName.LowerCaseEqualsLiteral("_parent")) {
  3198. GetSameTypeParent(getter_AddRefs(foundItem));
  3199. if (!foundItem) {
  3200. foundItem = this;
  3201. }
  3202. } else if (aName.LowerCaseEqualsLiteral("_top")) {
  3203. GetSameTypeRootTreeItem(getter_AddRefs(foundItem));
  3204. NS_ASSERTION(foundItem, "Must have this; worst case it's us!");
  3205. } else {
  3206. // Do the search for item by an actual name.
  3207. DoFindItemWithName(aName, aRequestor, aOriginalRequestor,
  3208. getter_AddRefs(foundItem));
  3209. }
  3210. if (foundItem && !CanAccessItem(foundItem, aOriginalRequestor)) {
  3211. foundItem = nullptr;
  3212. }
  3213. // DoFindItemWithName only returns active items and we don't check if
  3214. // the item is active for the special cases.
  3215. if (foundItem) {
  3216. foundItem.swap(*aResult);
  3217. }
  3218. return NS_OK;
  3219. }
  3220. }
  3221. void
  3222. nsDocShell::AssertOriginAttributesMatchPrivateBrowsing() {
  3223. // Chrome docshells must not have a private browsing OriginAttribute
  3224. // Content docshells must maintain the equality:
  3225. // mOriginAttributes.mPrivateBrowsingId == mPrivateBrowsingId
  3226. if (mItemType == typeChrome) {
  3227. MOZ_DIAGNOSTIC_ASSERT(mOriginAttributes.mPrivateBrowsingId == 0);
  3228. } else {
  3229. MOZ_DIAGNOSTIC_ASSERT(mOriginAttributes.mPrivateBrowsingId == mPrivateBrowsingId);
  3230. }
  3231. }
  3232. nsresult
  3233. nsDocShell::DoFindItemWithName(const nsAString& aName,
  3234. nsISupports* aRequestor,
  3235. nsIDocShellTreeItem* aOriginalRequestor,
  3236. nsIDocShellTreeItem** aResult)
  3237. {
  3238. // First we check our name.
  3239. if (mName.Equals(aName) && ItemIsActive(this) &&
  3240. CanAccessItem(this, aOriginalRequestor)) {
  3241. NS_ADDREF(*aResult = this);
  3242. return NS_OK;
  3243. }
  3244. // This QI may fail, but the places where we want to compare, comparing
  3245. // against nullptr serves the same purpose.
  3246. nsCOMPtr<nsIDocShellTreeItem> reqAsTreeItem(do_QueryInterface(aRequestor));
  3247. // Second we check our children making sure not to ask a child if
  3248. // it is the aRequestor.
  3249. #ifdef DEBUG
  3250. nsresult rv =
  3251. #endif
  3252. FindChildWithName(aName, true, true, reqAsTreeItem, aOriginalRequestor,
  3253. aResult);
  3254. NS_ASSERTION(NS_SUCCEEDED(rv),
  3255. "FindChildWithName should not be failing here.");
  3256. if (*aResult) {
  3257. return NS_OK;
  3258. }
  3259. // Third if we have a parent and it isn't the requestor then we
  3260. // should ask it to do the search. If it is the requestor we
  3261. // should just stop here and let the parent do the rest. If we
  3262. // don't have a parent, then we should ask the
  3263. // docShellTreeOwner to do the search.
  3264. nsCOMPtr<nsIDocShellTreeItem> parentAsTreeItem =
  3265. do_QueryInterface(GetAsSupports(mParent));
  3266. if (parentAsTreeItem) {
  3267. if (parentAsTreeItem == reqAsTreeItem) {
  3268. return NS_OK;
  3269. }
  3270. // If we have a same-type parent, respecting browser and app boundaries.
  3271. // NOTE: Could use GetSameTypeParent if the issues described in bug 1310344 are fixed.
  3272. if (!GetIsMozBrowserOrApp() && parentAsTreeItem->ItemType() == mItemType) {
  3273. return parentAsTreeItem->FindItemWithName(
  3274. aName,
  3275. static_cast<nsIDocShellTreeItem*>(this),
  3276. aOriginalRequestor,
  3277. aResult);
  3278. }
  3279. }
  3280. // If we have a null parent or the parent is not of the same type, we need to
  3281. // give up on finding it in our tree, and start looking in our TabGroup.
  3282. nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow();
  3283. if (window) {
  3284. RefPtr<mozilla::dom::TabGroup> tabGroup = window->TabGroup();
  3285. // We don't want to make the request to our TabGroup if they are the ones
  3286. // which made a request to us.
  3287. if (tabGroup != aRequestor) {
  3288. tabGroup->FindItemWithName(aName, this, aOriginalRequestor, aResult);
  3289. }
  3290. }
  3291. return NS_OK;
  3292. }
  3293. bool
  3294. nsDocShell::IsSandboxedFrom(nsIDocShell* aTargetDocShell)
  3295. {
  3296. // If no target then not sandboxed.
  3297. if (!aTargetDocShell) {
  3298. return false;
  3299. }
  3300. // We cannot be sandboxed from ourselves.
  3301. if (aTargetDocShell == this) {
  3302. return false;
  3303. }
  3304. // Default the sandbox flags to our flags, so that if we can't retrieve the
  3305. // active document, we will still enforce our own.
  3306. uint32_t sandboxFlags = mSandboxFlags;
  3307. if (mContentViewer) {
  3308. nsCOMPtr<nsIDocument> doc = mContentViewer->GetDocument();
  3309. if (doc) {
  3310. sandboxFlags = doc->GetSandboxFlags();
  3311. }
  3312. }
  3313. // If no flags, we are not sandboxed at all.
  3314. if (!sandboxFlags) {
  3315. return false;
  3316. }
  3317. // If aTargetDocShell has an ancestor, it is not top level.
  3318. nsCOMPtr<nsIDocShellTreeItem> ancestorOfTarget;
  3319. aTargetDocShell->GetSameTypeParent(getter_AddRefs(ancestorOfTarget));
  3320. if (ancestorOfTarget) {
  3321. do {
  3322. // We are not sandboxed if we are an ancestor of target.
  3323. if (ancestorOfTarget == this) {
  3324. return false;
  3325. }
  3326. nsCOMPtr<nsIDocShellTreeItem> tempTreeItem;
  3327. ancestorOfTarget->GetSameTypeParent(getter_AddRefs(tempTreeItem));
  3328. tempTreeItem.swap(ancestorOfTarget);
  3329. } while (ancestorOfTarget);
  3330. // Otherwise, we are sandboxed from aTargetDocShell.
  3331. return true;
  3332. }
  3333. // aTargetDocShell is top level, are we the "one permitted sandboxed
  3334. // navigator", i.e. did we open aTargetDocShell?
  3335. nsCOMPtr<nsIDocShell> permittedNavigator;
  3336. aTargetDocShell->GetOnePermittedSandboxedNavigator(
  3337. getter_AddRefs(permittedNavigator));
  3338. if (permittedNavigator == this) {
  3339. return false;
  3340. }
  3341. // If SANDBOXED_TOPLEVEL_NAVIGATION flag is not on, we are not sandboxed
  3342. // from our top.
  3343. if (!(sandboxFlags & SANDBOXED_TOPLEVEL_NAVIGATION)) {
  3344. nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
  3345. GetSameTypeRootTreeItem(getter_AddRefs(rootTreeItem));
  3346. if (SameCOMIdentity(aTargetDocShell, rootTreeItem)) {
  3347. return false;
  3348. }
  3349. }
  3350. // Otherwise, we are sandboxed from aTargetDocShell.
  3351. return true;
  3352. }
  3353. NS_IMETHODIMP
  3354. nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner)
  3355. {
  3356. NS_ENSURE_ARG_POINTER(aTreeOwner);
  3357. *aTreeOwner = mTreeOwner;
  3358. NS_IF_ADDREF(*aTreeOwner);
  3359. return NS_OK;
  3360. }
  3361. #ifdef DEBUG_DOCSHELL_FOCUS
  3362. static void
  3363. PrintDocTree(nsIDocShellTreeItem* aParentNode, int aLevel)
  3364. {
  3365. for (int32_t i = 0; i < aLevel; i++) {
  3366. printf(" ");
  3367. }
  3368. int32_t childWebshellCount;
  3369. aParentNode->GetChildCount(&childWebshellCount);
  3370. nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(aParentNode));
  3371. int32_t type = aParentNode->ItemType();
  3372. nsCOMPtr<nsIPresShell> presShell = parentAsDocShell->GetPresShell();
  3373. RefPtr<nsPresContext> presContext;
  3374. parentAsDocShell->GetPresContext(getter_AddRefs(presContext));
  3375. nsIDocument* doc = presShell->GetDocument();
  3376. nsCOMPtr<nsPIDOMWindowOuter> domwin(doc->GetWindow());
  3377. nsCOMPtr<nsIWidget> widget;
  3378. nsViewManager* vm = presShell->GetViewManager();
  3379. if (vm) {
  3380. vm->GetWidget(getter_AddRefs(widget));
  3381. }
  3382. dom::Element* rootElement = doc->GetRootElement();
  3383. printf("DS %p Ty %s Doc %p DW %p EM %p CN %p\n",
  3384. (void*)parentAsDocShell.get(),
  3385. type == nsIDocShellTreeItem::typeChrome ? "Chr" : "Con",
  3386. (void*)doc, (void*)domwin.get(),
  3387. (void*)presContext->EventStateManager(), (void*)rootElement);
  3388. if (childWebshellCount > 0) {
  3389. for (int32_t i = 0; i < childWebshellCount; i++) {
  3390. nsCOMPtr<nsIDocShellTreeItem> child;
  3391. aParentNode->GetChildAt(i, getter_AddRefs(child));
  3392. PrintDocTree(child, aLevel + 1);
  3393. }
  3394. }
  3395. }
  3396. static void
  3397. PrintDocTree(nsIDocShellTreeItem* aParentNode)
  3398. {
  3399. NS_ASSERTION(aParentNode, "Pointer is null!");
  3400. nsCOMPtr<nsIDocShellTreeItem> parentItem;
  3401. aParentNode->GetParent(getter_AddRefs(parentItem));
  3402. while (parentItem) {
  3403. nsCOMPtr<nsIDocShellTreeItem> tmp;
  3404. parentItem->GetParent(getter_AddRefs(tmp));
  3405. if (!tmp) {
  3406. break;
  3407. }
  3408. parentItem = tmp;
  3409. }
  3410. if (!parentItem) {
  3411. parentItem = aParentNode;
  3412. }
  3413. PrintDocTree(parentItem, 0);
  3414. }
  3415. #endif
  3416. NS_IMETHODIMP
  3417. nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner)
  3418. {
  3419. #ifdef DEBUG_DOCSHELL_FOCUS
  3420. nsCOMPtr<nsIDocShellTreeItem> item(do_QueryInterface(aTreeOwner));
  3421. if (item) {
  3422. PrintDocTree(item);
  3423. }
  3424. #endif
  3425. // Don't automatically set the progress based on the tree owner for frames
  3426. if (!IsFrame()) {
  3427. nsCOMPtr<nsIWebProgress> webProgress =
  3428. do_QueryInterface(GetAsSupports(this));
  3429. if (webProgress) {
  3430. nsCOMPtr<nsIWebProgressListener> oldListener =
  3431. do_QueryInterface(mTreeOwner);
  3432. nsCOMPtr<nsIWebProgressListener> newListener =
  3433. do_QueryInterface(aTreeOwner);
  3434. if (oldListener) {
  3435. webProgress->RemoveProgressListener(oldListener);
  3436. }
  3437. if (newListener) {
  3438. webProgress->AddProgressListener(newListener,
  3439. nsIWebProgress::NOTIFY_ALL);
  3440. }
  3441. }
  3442. }
  3443. mTreeOwner = aTreeOwner; // Weak reference per API
  3444. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  3445. while (iter.HasMore()) {
  3446. nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(iter.GetNext());
  3447. NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
  3448. if (child->ItemType() == mItemType) {
  3449. child->SetTreeOwner(aTreeOwner);
  3450. }
  3451. }
  3452. // Our tree owner has changed. Recompute scriptability.
  3453. //
  3454. // Note that this is near-redundant with the recomputation in
  3455. // SetDocLoaderParent(), but not so for the root DocShell, where the call to
  3456. // SetTreeOwner() happens after the initial AddDocLoaderAsChildOfRoot(),
  3457. // and we never set another parent. Given that this is neither expensive nor
  3458. // performance-critical, let's be safe and unconditionally recompute this
  3459. // state whenever dependent state changes.
  3460. RecomputeCanExecuteScripts();
  3461. return NS_OK;
  3462. }
  3463. NS_IMETHODIMP
  3464. nsDocShell::SetChildOffset(uint32_t aChildOffset)
  3465. {
  3466. mChildOffset = aChildOffset;
  3467. return NS_OK;
  3468. }
  3469. NS_IMETHODIMP
  3470. nsDocShell::GetHistoryID(uint64_t* aID)
  3471. {
  3472. *aID = mHistoryID;
  3473. return NS_OK;
  3474. }
  3475. NS_IMETHODIMP
  3476. nsDocShell::GetIsInUnload(bool* aIsInUnload)
  3477. {
  3478. *aIsInUnload = mFiredUnloadEvent;
  3479. return NS_OK;
  3480. }
  3481. NS_IMETHODIMP
  3482. nsDocShell::GetChildCount(int32_t* aChildCount)
  3483. {
  3484. NS_ENSURE_ARG_POINTER(aChildCount);
  3485. *aChildCount = mChildList.Length();
  3486. return NS_OK;
  3487. }
  3488. NS_IMETHODIMP
  3489. nsDocShell::AddChild(nsIDocShellTreeItem* aChild)
  3490. {
  3491. NS_ENSURE_ARG_POINTER(aChild);
  3492. RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
  3493. NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED);
  3494. // Make sure we're not creating a loop in the docshell tree
  3495. nsDocLoader* ancestor = this;
  3496. do {
  3497. if (childAsDocLoader == ancestor) {
  3498. return NS_ERROR_ILLEGAL_VALUE;
  3499. }
  3500. ancestor = ancestor->GetParent();
  3501. } while (ancestor);
  3502. // Make sure to remove the child from its current parent.
  3503. nsDocLoader* childsParent = childAsDocLoader->GetParent();
  3504. if (childsParent) {
  3505. nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader);
  3506. NS_ENSURE_SUCCESS(rv, rv);
  3507. }
  3508. // Make sure to clear the treeowner in case this child is a different type
  3509. // from us.
  3510. aChild->SetTreeOwner(nullptr);
  3511. nsresult res = AddChildLoader(childAsDocLoader);
  3512. NS_ENSURE_SUCCESS(res, res);
  3513. NS_ASSERTION(!mChildList.IsEmpty(),
  3514. "child list must not be empty after a successful add");
  3515. nsCOMPtr<nsIDocShell> childDocShell = do_QueryInterface(aChild);
  3516. bool dynamic = false;
  3517. childDocShell->GetCreatedDynamically(&dynamic);
  3518. if (!dynamic) {
  3519. nsCOMPtr<nsISHEntry> currentSH;
  3520. bool oshe = false;
  3521. GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
  3522. if (currentSH) {
  3523. currentSH->HasDynamicallyAddedChild(&dynamic);
  3524. }
  3525. }
  3526. childDocShell->SetChildOffset(dynamic ? -1 : mChildList.Length() - 1);
  3527. /* Set the child's global history if the parent has one */
  3528. if (mUseGlobalHistory) {
  3529. childDocShell->SetUseGlobalHistory(true);
  3530. }
  3531. if (aChild->ItemType() != mItemType) {
  3532. return NS_OK;
  3533. }
  3534. aChild->SetTreeOwner(mTreeOwner);
  3535. nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild));
  3536. if (!childAsDocShell) {
  3537. return NS_OK;
  3538. }
  3539. // charset, style-disabling, and zoom will be inherited in SetupNewViewer()
  3540. // Now take this document's charset and set the child's parentCharset field
  3541. // to it. We'll later use that field, in the loading process, for the
  3542. // charset choosing algorithm.
  3543. // If we fail, at any point, we just return NS_OK.
  3544. // This code has some performance impact. But this will be reduced when
  3545. // the current charset will finally be stored as an Atom, avoiding the
  3546. // alias resolution extra look-up.
  3547. // we are NOT going to propagate the charset is this Chrome's docshell
  3548. if (mItemType == nsIDocShellTreeItem::typeChrome) {
  3549. return NS_OK;
  3550. }
  3551. // get the parent's current charset
  3552. if (!mContentViewer) {
  3553. return NS_OK;
  3554. }
  3555. nsIDocument* doc = mContentViewer->GetDocument();
  3556. if (!doc) {
  3557. return NS_OK;
  3558. }
  3559. bool isWyciwyg = false;
  3560. if (mCurrentURI) {
  3561. // Check if the url is wyciwyg
  3562. mCurrentURI->SchemeIs("wyciwyg", &isWyciwyg);
  3563. }
  3564. if (!isWyciwyg) {
  3565. // If this docshell is loaded from a wyciwyg: URI, don't
  3566. // advertise our charset since it does not in any way reflect
  3567. // the actual source charset, which is what we're trying to
  3568. // expose here.
  3569. const nsACString& parentCS = doc->GetDocumentCharacterSet();
  3570. int32_t charsetSource = doc->GetDocumentCharacterSetSource();
  3571. // set the child's parentCharset
  3572. childAsDocShell->SetParentCharset(parentCS,
  3573. charsetSource,
  3574. doc->NodePrincipal());
  3575. }
  3576. // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n",
  3577. // NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType);
  3578. return NS_OK;
  3579. }
  3580. NS_IMETHODIMP
  3581. nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild)
  3582. {
  3583. NS_ENSURE_ARG_POINTER(aChild);
  3584. RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
  3585. NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED);
  3586. nsresult rv = RemoveChildLoader(childAsDocLoader);
  3587. NS_ENSURE_SUCCESS(rv, rv);
  3588. aChild->SetTreeOwner(nullptr);
  3589. return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader);
  3590. }
  3591. NS_IMETHODIMP
  3592. nsDocShell::GetChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild)
  3593. {
  3594. NS_ENSURE_ARG_POINTER(aChild);
  3595. #ifdef DEBUG
  3596. if (aIndex < 0) {
  3597. NS_WARNING("Negative index passed to GetChildAt");
  3598. } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) {
  3599. NS_WARNING("Too large an index passed to GetChildAt");
  3600. }
  3601. #endif
  3602. nsIDocumentLoader* child = ChildAt(aIndex);
  3603. NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED);
  3604. return CallQueryInterface(child, aChild);
  3605. }
  3606. NS_IMETHODIMP
  3607. nsDocShell::FindChildWithName(const nsAString& aName,
  3608. bool aRecurse, bool aSameType,
  3609. nsIDocShellTreeItem* aRequestor,
  3610. nsIDocShellTreeItem* aOriginalRequestor,
  3611. nsIDocShellTreeItem** aResult)
  3612. {
  3613. NS_ENSURE_ARG_POINTER(aResult);
  3614. // if we don't find one, we return NS_OK and a null result
  3615. *aResult = nullptr;
  3616. if (aName.IsEmpty()) {
  3617. return NS_OK;
  3618. }
  3619. nsXPIDLString childName;
  3620. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  3621. while (iter.HasMore()) {
  3622. nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(iter.GetNext());
  3623. NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
  3624. int32_t childType = child->ItemType();
  3625. if (aSameType && (childType != mItemType)) {
  3626. continue;
  3627. }
  3628. bool childNameEquals = false;
  3629. child->NameEquals(aName, &childNameEquals);
  3630. if (childNameEquals && ItemIsActive(child) &&
  3631. CanAccessItem(child, aOriginalRequestor)) {
  3632. child.swap(*aResult);
  3633. break;
  3634. }
  3635. // Only ask it to check children if it is same type
  3636. if (childType != mItemType) {
  3637. continue;
  3638. }
  3639. // Only ask the child if it isn't the requestor
  3640. if (aRecurse && (aRequestor != child)) {
  3641. // See if child contains the shell with the given name
  3642. #ifdef DEBUG
  3643. nsresult rv =
  3644. #endif
  3645. child->FindChildWithName(aName, true, aSameType,
  3646. static_cast<nsIDocShellTreeItem*>(this),
  3647. aOriginalRequestor, aResult);
  3648. NS_ASSERTION(NS_SUCCEEDED(rv), "FindChildWithName should not fail here");
  3649. if (*aResult) {
  3650. // found it
  3651. return NS_OK;
  3652. }
  3653. }
  3654. }
  3655. return NS_OK;
  3656. }
  3657. NS_IMETHODIMP
  3658. nsDocShell::GetChildSHEntry(int32_t aChildOffset, nsISHEntry** aResult)
  3659. {
  3660. nsresult rv = NS_OK;
  3661. NS_ENSURE_ARG_POINTER(aResult);
  3662. *aResult = nullptr;
  3663. // A nsISHEntry for a child is *only* available when the parent is in
  3664. // the progress of loading a document too...
  3665. if (mLSHE) {
  3666. /* Before looking for the subframe's url, check
  3667. * the expiration status of the parent. If the parent
  3668. * has expired from cache, then subframes will not be
  3669. * loaded from history in certain situations.
  3670. */
  3671. bool parentExpired = false;
  3672. mLSHE->GetExpirationStatus(&parentExpired);
  3673. /* Get the parent's Load Type so that it can be set on the child too.
  3674. * By default give a loadHistory value
  3675. */
  3676. uint32_t loadType = nsIDocShellLoadInfo::loadHistory;
  3677. mLSHE->GetLoadType(&loadType);
  3678. // If the user did a shift-reload on this frameset page,
  3679. // we don't want to load the subframes from history.
  3680. if (loadType == nsIDocShellLoadInfo::loadReloadBypassCache ||
  3681. loadType == nsIDocShellLoadInfo::loadReloadBypassProxy ||
  3682. loadType == nsIDocShellLoadInfo::loadReloadBypassProxyAndCache ||
  3683. loadType == nsIDocShellLoadInfo::loadRefresh) {
  3684. return rv;
  3685. }
  3686. /* If the user pressed reload and the parent frame has expired
  3687. * from cache, we do not want to load the child frame from history.
  3688. */
  3689. if (parentExpired && (loadType == nsIDocShellLoadInfo::loadReloadNormal)) {
  3690. // The parent has expired. Return null.
  3691. *aResult = nullptr;
  3692. return rv;
  3693. }
  3694. nsCOMPtr<nsISHContainer> container(do_QueryInterface(mLSHE));
  3695. if (container) {
  3696. // Get the child subframe from session history.
  3697. rv = container->GetChildAt(aChildOffset, aResult);
  3698. if (*aResult) {
  3699. (*aResult)->SetLoadType(loadType);
  3700. }
  3701. }
  3702. }
  3703. return rv;
  3704. }
  3705. NS_IMETHODIMP
  3706. nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
  3707. int32_t aChildOffset, uint32_t aLoadType,
  3708. bool aCloneChildren)
  3709. {
  3710. nsresult rv = NS_OK;
  3711. if (mLSHE && aLoadType != LOAD_PUSHSTATE) {
  3712. /* You get here if you are currently building a
  3713. * hierarchy ie.,you just visited a frameset page
  3714. */
  3715. nsCOMPtr<nsISHContainer> container(do_QueryInterface(mLSHE, &rv));
  3716. if (container) {
  3717. if (NS_FAILED(container->ReplaceChild(aNewEntry))) {
  3718. rv = container->AddChild(aNewEntry, aChildOffset);
  3719. }
  3720. }
  3721. } else if (!aCloneRef) {
  3722. /* This is an initial load in some subframe. Just append it if we can */
  3723. nsCOMPtr<nsISHContainer> container(do_QueryInterface(mOSHE, &rv));
  3724. if (container) {
  3725. rv = container->AddChild(aNewEntry, aChildOffset);
  3726. }
  3727. } else {
  3728. rv = AddChildSHEntryInternal(aCloneRef, aNewEntry, aChildOffset,
  3729. aLoadType, aCloneChildren);
  3730. }
  3731. return rv;
  3732. }
  3733. nsresult
  3734. nsDocShell::AddChildSHEntryInternal(nsISHEntry* aCloneRef,
  3735. nsISHEntry* aNewEntry,
  3736. int32_t aChildOffset,
  3737. uint32_t aLoadType,
  3738. bool aCloneChildren)
  3739. {
  3740. nsresult rv = NS_OK;
  3741. if (mSessionHistory) {
  3742. /* You are currently in the rootDocShell.
  3743. * You will get here when a subframe has a new url
  3744. * to load and you have walked up the tree all the
  3745. * way to the top to clone the current SHEntry hierarchy
  3746. * and replace the subframe where a new url was loaded with
  3747. * a new entry.
  3748. */
  3749. int32_t index = -1;
  3750. nsCOMPtr<nsISHEntry> currentHE;
  3751. mSessionHistory->GetIndex(&index);
  3752. if (index < 0) {
  3753. return NS_ERROR_FAILURE;
  3754. }
  3755. rv = mSessionHistory->GetEntryAtIndex(index, false,
  3756. getter_AddRefs(currentHE));
  3757. NS_ENSURE_TRUE(currentHE, NS_ERROR_FAILURE);
  3758. nsCOMPtr<nsISHEntry> currentEntry(do_QueryInterface(currentHE));
  3759. if (currentEntry) {
  3760. uint32_t cloneID = 0;
  3761. nsCOMPtr<nsISHEntry> nextEntry;
  3762. aCloneRef->GetID(&cloneID);
  3763. rv = CloneAndReplace(currentEntry, this, cloneID, aNewEntry,
  3764. aCloneChildren, getter_AddRefs(nextEntry));
  3765. if (NS_SUCCEEDED(rv)) {
  3766. nsCOMPtr<nsISHistoryInternal> shPrivate =
  3767. do_QueryInterface(mSessionHistory);
  3768. NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE);
  3769. rv = shPrivate->AddEntry(nextEntry, true);
  3770. }
  3771. }
  3772. } else {
  3773. /* Just pass this along */
  3774. nsCOMPtr<nsIDocShell> parent =
  3775. do_QueryInterface(GetAsSupports(mParent), &rv);
  3776. if (parent) {
  3777. rv = static_cast<nsDocShell*>(parent.get())->AddChildSHEntryInternal(
  3778. aCloneRef, aNewEntry, aChildOffset, aLoadType, aCloneChildren);
  3779. }
  3780. }
  3781. return rv;
  3782. }
  3783. nsresult
  3784. nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry, int32_t aChildOffset,
  3785. bool aCloneChildren)
  3786. {
  3787. /* You will get here when you are in a subframe and
  3788. * a new url has been loaded on you.
  3789. * The mOSHE in this subframe will be the previous url's
  3790. * mOSHE. This mOSHE will be used as the identification
  3791. * for this subframe in the CloneAndReplace function.
  3792. */
  3793. // In this case, we will end up calling AddEntry, which increases the
  3794. // current index by 1
  3795. nsCOMPtr<nsISHistory> rootSH;
  3796. GetRootSessionHistory(getter_AddRefs(rootSH));
  3797. if (rootSH) {
  3798. rootSH->GetIndex(&mPreviousTransIndex);
  3799. }
  3800. nsresult rv;
  3801. nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv);
  3802. if (parent) {
  3803. rv = parent->AddChildSHEntry(mOSHE, aNewEntry, aChildOffset, mLoadType,
  3804. aCloneChildren);
  3805. }
  3806. if (rootSH) {
  3807. rootSH->GetIndex(&mLoadedTransIndex);
  3808. #ifdef DEBUG_PAGE_CACHE
  3809. printf("Previous index: %d, Loaded index: %d\n\n", mPreviousTransIndex,
  3810. mLoadedTransIndex);
  3811. #endif
  3812. }
  3813. return rv;
  3814. }
  3815. NS_IMETHODIMP
  3816. nsDocShell::SetUseGlobalHistory(bool aUseGlobalHistory)
  3817. {
  3818. nsresult rv;
  3819. mUseGlobalHistory = aUseGlobalHistory;
  3820. if (!aUseGlobalHistory) {
  3821. mGlobalHistory = nullptr;
  3822. return NS_OK;
  3823. }
  3824. // No need to initialize mGlobalHistory if IHistory is available.
  3825. nsCOMPtr<IHistory> history = services::GetHistoryService();
  3826. if (history) {
  3827. return NS_OK;
  3828. }
  3829. if (mGlobalHistory) {
  3830. return NS_OK;
  3831. }
  3832. mGlobalHistory = do_GetService(NS_GLOBALHISTORY2_CONTRACTID, &rv);
  3833. return rv;
  3834. }
  3835. NS_IMETHODIMP
  3836. nsDocShell::GetUseGlobalHistory(bool* aUseGlobalHistory)
  3837. {
  3838. *aUseGlobalHistory = mUseGlobalHistory;
  3839. return NS_OK;
  3840. }
  3841. NS_IMETHODIMP
  3842. nsDocShell::RemoveFromSessionHistory()
  3843. {
  3844. nsCOMPtr<nsISHistoryInternal> internalHistory;
  3845. nsCOMPtr<nsISHistory> sessionHistory;
  3846. nsCOMPtr<nsIDocShellTreeItem> root;
  3847. GetSameTypeRootTreeItem(getter_AddRefs(root));
  3848. if (root) {
  3849. nsCOMPtr<nsIWebNavigation> rootAsWebnav = do_QueryInterface(root);
  3850. if (rootAsWebnav) {
  3851. rootAsWebnav->GetSessionHistory(getter_AddRefs(sessionHistory));
  3852. internalHistory = do_QueryInterface(sessionHistory);
  3853. }
  3854. }
  3855. if (!internalHistory) {
  3856. return NS_OK;
  3857. }
  3858. int32_t index = 0;
  3859. sessionHistory->GetIndex(&index);
  3860. AutoTArray<uint64_t, 16> ids({mHistoryID});
  3861. internalHistory->RemoveEntries(ids, index);
  3862. return NS_OK;
  3863. }
  3864. NS_IMETHODIMP
  3865. nsDocShell::SetCreatedDynamically(bool aDynamic)
  3866. {
  3867. mDynamicallyCreated = aDynamic;
  3868. return NS_OK;
  3869. }
  3870. NS_IMETHODIMP
  3871. nsDocShell::GetCreatedDynamically(bool* aDynamic)
  3872. {
  3873. *aDynamic = mDynamicallyCreated;
  3874. return NS_OK;
  3875. }
  3876. NS_IMETHODIMP
  3877. nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE)
  3878. {
  3879. *aOSHE = false;
  3880. *aEntry = nullptr;
  3881. if (mLSHE) {
  3882. NS_ADDREF(*aEntry = mLSHE);
  3883. } else if (mOSHE) {
  3884. NS_ADDREF(*aEntry = mOSHE);
  3885. *aOSHE = true;
  3886. }
  3887. return NS_OK;
  3888. }
  3889. nsIScriptGlobalObject*
  3890. nsDocShell::GetScriptGlobalObject()
  3891. {
  3892. NS_ENSURE_SUCCESS(EnsureScriptEnvironment(), nullptr);
  3893. return mScriptGlobal;
  3894. }
  3895. nsIDocument*
  3896. nsDocShell::GetDocument()
  3897. {
  3898. NS_ENSURE_SUCCESS(EnsureContentViewer(), nullptr);
  3899. return mContentViewer->GetDocument();
  3900. }
  3901. nsPIDOMWindowOuter*
  3902. nsDocShell::GetWindow()
  3903. {
  3904. if (NS_FAILED(EnsureScriptEnvironment())) {
  3905. return nullptr;
  3906. }
  3907. return mScriptGlobal->AsOuter();
  3908. }
  3909. NS_IMETHODIMP
  3910. nsDocShell::SetDeviceSizeIsPageSize(bool aValue)
  3911. {
  3912. if (mDeviceSizeIsPageSize != aValue) {
  3913. mDeviceSizeIsPageSize = aValue;
  3914. RefPtr<nsPresContext> presContext;
  3915. GetPresContext(getter_AddRefs(presContext));
  3916. if (presContext) {
  3917. presContext->MediaFeatureValuesChanged(nsRestyleHint(0));
  3918. }
  3919. }
  3920. return NS_OK;
  3921. }
  3922. NS_IMETHODIMP
  3923. nsDocShell::GetDeviceSizeIsPageSize(bool* aValue)
  3924. {
  3925. *aValue = mDeviceSizeIsPageSize;
  3926. return NS_OK;
  3927. }
  3928. void
  3929. nsDocShell::ClearFrameHistory(nsISHEntry* aEntry)
  3930. {
  3931. nsCOMPtr<nsISHContainer> shcontainer = do_QueryInterface(aEntry);
  3932. nsCOMPtr<nsISHistory> rootSH;
  3933. GetRootSessionHistory(getter_AddRefs(rootSH));
  3934. nsCOMPtr<nsISHistoryInternal> history = do_QueryInterface(rootSH);
  3935. if (!history || !shcontainer) {
  3936. return;
  3937. }
  3938. int32_t count = 0;
  3939. shcontainer->GetChildCount(&count);
  3940. AutoTArray<uint64_t, 16> ids;
  3941. for (int32_t i = 0; i < count; ++i) {
  3942. nsCOMPtr<nsISHEntry> child;
  3943. shcontainer->GetChildAt(i, getter_AddRefs(child));
  3944. if (child) {
  3945. uint64_t id = 0;
  3946. child->GetDocshellID(&id);
  3947. ids.AppendElement(id);
  3948. }
  3949. }
  3950. int32_t index = 0;
  3951. rootSH->GetIndex(&index);
  3952. history->RemoveEntries(ids, index);
  3953. }
  3954. //-------------------------------------
  3955. //-- Helper Method for Print discovery
  3956. //-------------------------------------
  3957. bool
  3958. nsDocShell::IsPrintingOrPP(bool aDisplayErrorDialog)
  3959. {
  3960. if (mIsPrintingOrPP && aDisplayErrorDialog) {
  3961. DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr);
  3962. }
  3963. return mIsPrintingOrPP;
  3964. }
  3965. bool
  3966. nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog,
  3967. bool aCheckIfUnloadFired)
  3968. {
  3969. bool isAllowed = !IsPrintingOrPP(aDisplayPrintErrorDialog) &&
  3970. (!aCheckIfUnloadFired || !mFiredUnloadEvent);
  3971. if (!isAllowed) {
  3972. return false;
  3973. }
  3974. if (!mContentViewer) {
  3975. return true;
  3976. }
  3977. bool firingBeforeUnload;
  3978. mContentViewer->GetBeforeUnloadFiring(&firingBeforeUnload);
  3979. return !firingBeforeUnload;
  3980. }
  3981. //*****************************************************************************
  3982. // nsDocShell::nsIWebNavigation
  3983. //*****************************************************************************
  3984. NS_IMETHODIMP
  3985. nsDocShell::GetCanGoBack(bool* aCanGoBack)
  3986. {
  3987. if (!IsNavigationAllowed(false)) {
  3988. *aCanGoBack = false;
  3989. return NS_OK; // JS may not handle returning of an error code
  3990. }
  3991. nsresult rv;
  3992. nsCOMPtr<nsISHistory> rootSH;
  3993. rv = GetRootSessionHistory(getter_AddRefs(rootSH));
  3994. nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(rootSH));
  3995. NS_ENSURE_TRUE(webnav, NS_ERROR_FAILURE);
  3996. rv = webnav->GetCanGoBack(aCanGoBack);
  3997. return rv;
  3998. }
  3999. NS_IMETHODIMP
  4000. nsDocShell::GetCanGoForward(bool* aCanGoForward)
  4001. {
  4002. if (!IsNavigationAllowed(false)) {
  4003. *aCanGoForward = false;
  4004. return NS_OK; // JS may not handle returning of an error code
  4005. }
  4006. nsresult rv;
  4007. nsCOMPtr<nsISHistory> rootSH;
  4008. rv = GetRootSessionHistory(getter_AddRefs(rootSH));
  4009. nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(rootSH));
  4010. NS_ENSURE_TRUE(webnav, NS_ERROR_FAILURE);
  4011. rv = webnav->GetCanGoForward(aCanGoForward);
  4012. return rv;
  4013. }
  4014. NS_IMETHODIMP
  4015. nsDocShell::GoBack()
  4016. {
  4017. if (!IsNavigationAllowed()) {
  4018. return NS_OK; // JS may not handle returning of an error code
  4019. }
  4020. nsresult rv;
  4021. nsCOMPtr<nsISHistory> rootSH;
  4022. rv = GetRootSessionHistory(getter_AddRefs(rootSH));
  4023. nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(rootSH));
  4024. NS_ENSURE_TRUE(webnav, NS_ERROR_FAILURE);
  4025. rv = webnav->GoBack();
  4026. return rv;
  4027. }
  4028. NS_IMETHODIMP
  4029. nsDocShell::GoForward()
  4030. {
  4031. if (!IsNavigationAllowed()) {
  4032. return NS_OK; // JS may not handle returning of an error code
  4033. }
  4034. nsresult rv;
  4035. nsCOMPtr<nsISHistory> rootSH;
  4036. rv = GetRootSessionHistory(getter_AddRefs(rootSH));
  4037. nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(rootSH));
  4038. NS_ENSURE_TRUE(webnav, NS_ERROR_FAILURE);
  4039. rv = webnav->GoForward();
  4040. return rv;
  4041. }
  4042. NS_IMETHODIMP
  4043. nsDocShell::GotoIndex(int32_t aIndex)
  4044. {
  4045. if (!IsNavigationAllowed()) {
  4046. return NS_OK; // JS may not handle returning of an error code
  4047. }
  4048. nsresult rv;
  4049. nsCOMPtr<nsISHistory> rootSH;
  4050. rv = GetRootSessionHistory(getter_AddRefs(rootSH));
  4051. nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(rootSH));
  4052. NS_ENSURE_TRUE(webnav, NS_ERROR_FAILURE);
  4053. rv = webnav->GotoIndex(aIndex);
  4054. return rv;
  4055. }
  4056. NS_IMETHODIMP
  4057. nsDocShell::LoadURI(const char16_t* aURI,
  4058. uint32_t aLoadFlags,
  4059. nsIURI* aReferringURI,
  4060. nsIInputStream* aPostStream,
  4061. nsIInputStream* aHeaderStream)
  4062. {
  4063. return LoadURIWithOptions(aURI, aLoadFlags, aReferringURI,
  4064. mozilla::net::RP_Default, aPostStream,
  4065. aHeaderStream, nullptr, nullptr);
  4066. }
  4067. NS_IMETHODIMP
  4068. nsDocShell::LoadURIWithOptions(const char16_t* aURI,
  4069. uint32_t aLoadFlags,
  4070. nsIURI* aReferringURI,
  4071. uint32_t aReferrerPolicy,
  4072. nsIInputStream* aPostStream,
  4073. nsIInputStream* aHeaderStream,
  4074. nsIURI* aBaseURI,
  4075. nsIPrincipal* aTriggeringPrincipal)
  4076. {
  4077. NS_ASSERTION((aLoadFlags & 0xf) == 0, "Unexpected flags");
  4078. if (!IsNavigationAllowed()) {
  4079. return NS_OK; // JS may not handle returning of an error code
  4080. }
  4081. nsCOMPtr<nsIURI> uri;
  4082. nsCOMPtr<nsIInputStream> postStream(aPostStream);
  4083. nsresult rv = NS_OK;
  4084. // Create a URI from our string; if that succeeds, we want to
  4085. // change aLoadFlags to not include the ALLOW_THIRD_PARTY_FIXUP
  4086. // flag.
  4087. NS_ConvertUTF16toUTF8 uriString(aURI);
  4088. // Cleanup the empty spaces that might be on each end.
  4089. uriString.Trim(" ");
  4090. // Eliminate embedded newlines, which single-line text fields now allow:
  4091. uriString.StripChars("\r\n");
  4092. NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE);
  4093. rv = NS_NewURI(getter_AddRefs(uri), uriString);
  4094. if (uri) {
  4095. aLoadFlags &= ~LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
  4096. }
  4097. nsCOMPtr<nsIURIFixupInfo> fixupInfo;
  4098. if (sURIFixup) {
  4099. // Call the fixup object. This will clobber the rv from NS_NewURI
  4100. // above, but that's fine with us. Note that we need to do this even
  4101. // if NS_NewURI returned a URI, because fixup handles nested URIs, etc
  4102. // (things like view-source:mozilla.org for example).
  4103. uint32_t fixupFlags = 0;
  4104. if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
  4105. fixupFlags |= nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
  4106. }
  4107. if (aLoadFlags & LOAD_FLAGS_FIXUP_SCHEME_TYPOS) {
  4108. fixupFlags |= nsIURIFixup::FIXUP_FLAG_FIX_SCHEME_TYPOS;
  4109. }
  4110. nsCOMPtr<nsIInputStream> fixupStream;
  4111. rv = sURIFixup->GetFixupURIInfo(uriString, fixupFlags,
  4112. getter_AddRefs(fixupStream),
  4113. getter_AddRefs(fixupInfo));
  4114. if (NS_SUCCEEDED(rv)) {
  4115. fixupInfo->GetPreferredURI(getter_AddRefs(uri));
  4116. fixupInfo->SetConsumer(GetAsSupports(this));
  4117. }
  4118. if (fixupStream) {
  4119. // GetFixupURIInfo only returns a post data stream if it succeeded
  4120. // and changed the URI, in which case we should override the
  4121. // passed-in post data.
  4122. postStream = fixupStream;
  4123. }
  4124. if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
  4125. nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
  4126. if (serv) {
  4127. serv->NotifyObservers(fixupInfo, "keyword-uri-fixup", aURI);
  4128. }
  4129. }
  4130. }
  4131. // else no fixup service so just use the URI we created and see
  4132. // what happens
  4133. if (NS_ERROR_MALFORMED_URI == rv) {
  4134. if (DisplayLoadError(rv, uri, aURI, nullptr) &&
  4135. (aLoadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
  4136. return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
  4137. }
  4138. }
  4139. if (NS_FAILED(rv) || !uri) {
  4140. return NS_ERROR_FAILURE;
  4141. }
  4142. PopupControlState popupState;
  4143. if (aLoadFlags & LOAD_FLAGS_ALLOW_POPUPS) {
  4144. popupState = openAllowed;
  4145. aLoadFlags &= ~LOAD_FLAGS_ALLOW_POPUPS;
  4146. } else {
  4147. popupState = openOverridden;
  4148. }
  4149. nsAutoPopupStatePusher statePusher(popupState);
  4150. bool forceAllowDataURI =
  4151. aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
  4152. // Don't pass certain flags that aren't needed and end up confusing
  4153. // ConvertLoadTypeToDocShellLoadInfo. We do need to ensure that they are
  4154. // passed to LoadURI though, since it uses them.
  4155. uint32_t extraFlags = (aLoadFlags & EXTRA_LOAD_FLAGS);
  4156. aLoadFlags &= ~EXTRA_LOAD_FLAGS;
  4157. nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
  4158. rv = CreateLoadInfo(getter_AddRefs(loadInfo));
  4159. if (NS_FAILED(rv)) {
  4160. return rv;
  4161. }
  4162. /*
  4163. * If the user "Disables Protection on This Page", we have to make sure to
  4164. * remember the users decision when opening links in child tabs [Bug 906190]
  4165. */
  4166. uint32_t loadType;
  4167. if (aLoadFlags & LOAD_FLAGS_ALLOW_MIXED_CONTENT) {
  4168. loadType = MAKE_LOAD_TYPE(LOAD_NORMAL_ALLOW_MIXED_CONTENT, aLoadFlags);
  4169. } else {
  4170. loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
  4171. }
  4172. loadInfo->SetLoadType(ConvertLoadTypeToDocShellLoadInfo(loadType));
  4173. loadInfo->SetPostDataStream(postStream);
  4174. loadInfo->SetReferrer(aReferringURI);
  4175. loadInfo->SetReferrerPolicy(aReferrerPolicy);
  4176. loadInfo->SetHeadersStream(aHeaderStream);
  4177. loadInfo->SetBaseURI(aBaseURI);
  4178. loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
  4179. loadInfo->SetForceAllowDataURI(forceAllowDataURI);
  4180. if (fixupInfo) {
  4181. nsAutoString searchProvider, keyword;
  4182. fixupInfo->GetKeywordProviderName(searchProvider);
  4183. fixupInfo->GetKeywordAsSent(keyword);
  4184. MaybeNotifyKeywordSearchLoading(searchProvider, keyword);
  4185. }
  4186. rv = LoadURI(uri, loadInfo, extraFlags, true);
  4187. // Save URI string in case it's needed later when
  4188. // sending to search engine service in EndPageLoad()
  4189. mOriginalUriString = uriString;
  4190. return rv;
  4191. }
  4192. NS_IMETHODIMP
  4193. nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
  4194. const char16_t* aURL,
  4195. nsIChannel* aFailedChannel,
  4196. bool* aDisplayedErrorPage)
  4197. {
  4198. *aDisplayedErrorPage = false;
  4199. // Get prompt and string bundle servcies
  4200. nsCOMPtr<nsIPrompt> prompter;
  4201. nsCOMPtr<nsIStringBundle> stringBundle;
  4202. GetPromptAndStringBundle(getter_AddRefs(prompter),
  4203. getter_AddRefs(stringBundle));
  4204. NS_ENSURE_TRUE(stringBundle, NS_ERROR_FAILURE);
  4205. NS_ENSURE_TRUE(prompter, NS_ERROR_FAILURE);
  4206. nsAutoString error;
  4207. const uint32_t kMaxFormatStrArgs = 3;
  4208. nsAutoString formatStrs[kMaxFormatStrArgs];
  4209. uint32_t formatStrCount = 0;
  4210. bool addHostPort = false;
  4211. nsresult rv = NS_OK;
  4212. nsAutoString messageStr;
  4213. nsAutoCString cssClass;
  4214. nsAutoCString errorPage;
  4215. errorPage.AssignLiteral("neterror");
  4216. // Turn the error code into a human readable error message.
  4217. if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
  4218. NS_ENSURE_ARG_POINTER(aURI);
  4219. // Extract the schemes into a comma delimited list.
  4220. nsAutoCString scheme;
  4221. aURI->GetScheme(scheme);
  4222. CopyASCIItoUTF16(scheme, formatStrs[0]);
  4223. nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI);
  4224. while (nestedURI) {
  4225. nsCOMPtr<nsIURI> tempURI;
  4226. nsresult rv2;
  4227. rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI));
  4228. if (NS_SUCCEEDED(rv2) && tempURI) {
  4229. tempURI->GetScheme(scheme);
  4230. formatStrs[0].AppendLiteral(", ");
  4231. AppendASCIItoUTF16(scheme, formatStrs[0]);
  4232. }
  4233. nestedURI = do_QueryInterface(tempURI);
  4234. }
  4235. formatStrCount = 1;
  4236. error.AssignLiteral("unknownProtocolFound");
  4237. } else if (NS_ERROR_FILE_NOT_FOUND == aError) {
  4238. NS_ENSURE_ARG_POINTER(aURI);
  4239. error.AssignLiteral("fileNotFound");
  4240. } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) {
  4241. NS_ENSURE_ARG_POINTER(aURI);
  4242. error.AssignLiteral("fileAccessDenied");
  4243. } else if (NS_ERROR_UNKNOWN_HOST == aError) {
  4244. NS_ENSURE_ARG_POINTER(aURI);
  4245. // Get the host
  4246. nsAutoCString host;
  4247. nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI);
  4248. innermostURI->GetHost(host);
  4249. CopyUTF8toUTF16(host, formatStrs[0]);
  4250. formatStrCount = 1;
  4251. error.AssignLiteral("dnsNotFound");
  4252. } else if (NS_ERROR_CONNECTION_REFUSED == aError) {
  4253. NS_ENSURE_ARG_POINTER(aURI);
  4254. addHostPort = true;
  4255. error.AssignLiteral("connectionFailure");
  4256. } else if (NS_ERROR_NET_INTERRUPT == aError) {
  4257. NS_ENSURE_ARG_POINTER(aURI);
  4258. addHostPort = true;
  4259. error.AssignLiteral("netInterrupt");
  4260. } else if (NS_ERROR_NET_TIMEOUT == aError) {
  4261. NS_ENSURE_ARG_POINTER(aURI);
  4262. // Get the host
  4263. nsAutoCString host;
  4264. aURI->GetHost(host);
  4265. CopyUTF8toUTF16(host, formatStrs[0]);
  4266. formatStrCount = 1;
  4267. error.AssignLiteral("netTimeout");
  4268. } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError ||
  4269. NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError) {
  4270. // CSP error
  4271. cssClass.AssignLiteral("neterror");
  4272. error.AssignLiteral("cspBlocked");
  4273. } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY) {
  4274. nsCOMPtr<nsINSSErrorsService> nsserr =
  4275. do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID);
  4276. uint32_t errorClass;
  4277. if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))) {
  4278. errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL;
  4279. }
  4280. nsCOMPtr<nsISupports> securityInfo;
  4281. nsCOMPtr<nsITransportSecurityInfo> tsi;
  4282. if (aFailedChannel) {
  4283. aFailedChannel->GetSecurityInfo(getter_AddRefs(securityInfo));
  4284. }
  4285. tsi = do_QueryInterface(securityInfo);
  4286. if (tsi) {
  4287. uint32_t securityState;
  4288. tsi->GetSecurityState(&securityState);
  4289. if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) {
  4290. error.AssignLiteral("sslv3Used");
  4291. addHostPort = true;
  4292. } else if (securityState & nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
  4293. error.AssignLiteral("weakCryptoUsed");
  4294. addHostPort = true;
  4295. } else {
  4296. // Usually we should have aFailedChannel and get a detailed message
  4297. tsi->GetErrorMessage(getter_Copies(messageStr));
  4298. }
  4299. } else {
  4300. // No channel, let's obtain the generic error message
  4301. if (nsserr) {
  4302. nsserr->GetErrorMessage(aError, messageStr);
  4303. }
  4304. }
  4305. if (!messageStr.IsEmpty()) {
  4306. if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) {
  4307. error.AssignLiteral("nssBadCert");
  4308. // If this is an HTTP Strict Transport Security host, don't allow
  4309. // overrides (RFC 6797 section 12.1).
  4310. uint32_t flags =
  4311. UsePrivateBrowsing() ? nsISocketProvider::NO_PERMANENT_STORAGE : 0;
  4312. bool isStsHost = false;
  4313. if (XRE_IsParentProcess()) {
  4314. nsCOMPtr<nsISiteSecurityService> sss =
  4315. do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
  4316. NS_ENSURE_SUCCESS(rv, rv);
  4317. rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI,
  4318. flags, nullptr, &isStsHost);
  4319. NS_ENSURE_SUCCESS(rv, rv);
  4320. } else {
  4321. mozilla::dom::ContentChild* cc =
  4322. mozilla::dom::ContentChild::GetSingleton();
  4323. mozilla::ipc::URIParams uri;
  4324. SerializeURI(aURI, uri);
  4325. cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HSTS, uri, flags,
  4326. &isStsHost);
  4327. }
  4328. if (Preferences::GetBool(
  4329. "browser.xul.error_pages.expert_bad_cert", false)) {
  4330. cssClass.AssignLiteral("expertBadCert");
  4331. }
  4332. // HSTS takes precedence over the expert bad cert pref. We
  4333. // never want to show the "Add Exception" button for these sites.
  4334. if (isStsHost) {
  4335. cssClass.AssignLiteral("badStsCert");
  4336. }
  4337. // See if an alternate cert error page is registered
  4338. nsAdoptingCString alternateErrorPage =
  4339. Preferences::GetCString("security.alternate_certificate_error_page");
  4340. if (alternateErrorPage) {
  4341. errorPage.Assign(alternateErrorPage);
  4342. }
  4343. } else {
  4344. error.AssignLiteral("nssFailure2");
  4345. }
  4346. }
  4347. } else if (NS_ERROR_PHISHING_URI == aError ||
  4348. NS_ERROR_MALWARE_URI == aError ||
  4349. NS_ERROR_UNWANTED_URI == aError) {
  4350. nsAutoCString host;
  4351. aURI->GetHost(host);
  4352. CopyUTF8toUTF16(host, formatStrs[0]);
  4353. formatStrCount = 1;
  4354. // Malware and phishing detectors may want to use an alternate error
  4355. // page, but if the pref's not set, we'll fall back on the standard page
  4356. nsAdoptingCString alternateErrorPage =
  4357. Preferences::GetCString("urlclassifier.alternate_error_page");
  4358. if (alternateErrorPage) {
  4359. errorPage.Assign(alternateErrorPage);
  4360. }
  4361. if (NS_ERROR_PHISHING_URI == aError) {
  4362. error.AssignLiteral("deceptiveBlocked");
  4363. } else if (NS_ERROR_MALWARE_URI == aError) {
  4364. error.AssignLiteral("malwareBlocked");
  4365. } else if (NS_ERROR_UNWANTED_URI == aError) {
  4366. error.AssignLiteral("unwantedBlocked");
  4367. }
  4368. cssClass.AssignLiteral("blacklist");
  4369. } else if (NS_ERROR_CONTENT_CRASHED == aError) {
  4370. errorPage.AssignLiteral("tabcrashed");
  4371. error.AssignLiteral("tabcrashed");
  4372. nsCOMPtr<EventTarget> handler = mChromeEventHandler;
  4373. if (handler) {
  4374. nsCOMPtr<Element> element = do_QueryInterface(handler);
  4375. element->GetAttribute(NS_LITERAL_STRING("crashedPageTitle"), messageStr);
  4376. }
  4377. // DisplayLoadError requires a non-empty messageStr to proceed and call
  4378. // LoadErrorPage. If the page doesn't have a title, we will use a blank
  4379. // space which will be trimmed and thus treated as empty by the front-end.
  4380. if (messageStr.IsEmpty()) {
  4381. messageStr.AssignLiteral(u" ");
  4382. }
  4383. } else {
  4384. // Errors requiring simple formatting
  4385. switch (aError) {
  4386. case NS_ERROR_MALFORMED_URI:
  4387. // URI is malformed
  4388. error.AssignLiteral("malformedURI");
  4389. break;
  4390. case NS_ERROR_REDIRECT_LOOP:
  4391. // Doc failed to load because the server generated too many redirects
  4392. error.AssignLiteral("redirectLoop");
  4393. break;
  4394. case NS_ERROR_UNKNOWN_SOCKET_TYPE:
  4395. // Doc failed to load because PSM is not installed
  4396. error.AssignLiteral("unknownSocketType");
  4397. break;
  4398. case NS_ERROR_NET_RESET:
  4399. // Doc failed to load because the server kept reseting the connection
  4400. // before we could read any data from it
  4401. error.AssignLiteral("netReset");
  4402. break;
  4403. case NS_ERROR_DOCUMENT_NOT_CACHED:
  4404. // Doc failed to load because the cache does not contain a copy of
  4405. // the document.
  4406. error.AssignLiteral("notCached");
  4407. break;
  4408. case NS_ERROR_OFFLINE:
  4409. // Doc failed to load because we are offline.
  4410. error.AssignLiteral("netOffline");
  4411. break;
  4412. case NS_ERROR_DOCUMENT_IS_PRINTMODE:
  4413. // Doc navigation attempted while Printing or Print Preview
  4414. error.AssignLiteral("isprinting");
  4415. break;
  4416. case NS_ERROR_PORT_ACCESS_NOT_ALLOWED:
  4417. // Port blocked for security reasons
  4418. addHostPort = true;
  4419. error.AssignLiteral("deniedPortAccess");
  4420. break;
  4421. case NS_ERROR_UNKNOWN_PROXY_HOST:
  4422. // Proxy hostname could not be resolved.
  4423. error.AssignLiteral("proxyResolveFailure");
  4424. break;
  4425. case NS_ERROR_PROXY_CONNECTION_REFUSED:
  4426. // Proxy connection was refused.
  4427. error.AssignLiteral("proxyConnectFailure");
  4428. break;
  4429. case NS_ERROR_INVALID_CONTENT_ENCODING:
  4430. // Bad Content Encoding.
  4431. error.AssignLiteral("contentEncodingError");
  4432. break;
  4433. case NS_ERROR_REMOTE_XUL:
  4434. error.AssignLiteral("remoteXUL");
  4435. break;
  4436. case NS_ERROR_UNSAFE_CONTENT_TYPE:
  4437. // Channel refused to load from an unrecognized content type.
  4438. error.AssignLiteral("unsafeContentType");
  4439. break;
  4440. case NS_ERROR_CORRUPTED_CONTENT:
  4441. // Broken Content Detected. e.g. Content-MD5 check failure.
  4442. error.AssignLiteral("corruptedContentErrorv2");
  4443. break;
  4444. case NS_ERROR_INTERCEPTION_FAILED:
  4445. // ServiceWorker intercepted request, but something went wrong.
  4446. error.AssignLiteral("corruptedContentErrorv2");
  4447. break;
  4448. case NS_ERROR_NET_INADEQUATE_SECURITY:
  4449. // Server negotiated bad TLS for HTTP/2.
  4450. error.AssignLiteral("inadequateSecurityError");
  4451. addHostPort = true;
  4452. break;
  4453. default:
  4454. break;
  4455. }
  4456. }
  4457. // Test if the error should be displayed
  4458. if (error.IsEmpty()) {
  4459. return NS_OK;
  4460. }
  4461. // Test if the error needs to be formatted
  4462. if (!messageStr.IsEmpty()) {
  4463. // already obtained message
  4464. } else {
  4465. if (addHostPort) {
  4466. // Build up the host:port string.
  4467. nsAutoCString hostport;
  4468. if (aURI) {
  4469. aURI->GetHostPort(hostport);
  4470. } else {
  4471. hostport.Assign('?');
  4472. }
  4473. CopyUTF8toUTF16(hostport, formatStrs[formatStrCount++]);
  4474. }
  4475. nsAutoCString spec;
  4476. rv = NS_ERROR_NOT_AVAILABLE;
  4477. if (aURI) {
  4478. // displaying "file://" is aesthetically unpleasing and could even be
  4479. // confusing to the user
  4480. bool isFileURI = false;
  4481. rv = aURI->SchemeIs("file", &isFileURI);
  4482. if (NS_SUCCEEDED(rv) && isFileURI) {
  4483. aURI->GetPath(spec);
  4484. } else {
  4485. aURI->GetSpec(spec);
  4486. }
  4487. nsAutoCString charset;
  4488. // unescape and convert from origin charset
  4489. aURI->GetOriginCharset(charset);
  4490. nsCOMPtr<nsITextToSubURI> textToSubURI(
  4491. do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv));
  4492. if (NS_SUCCEEDED(rv)) {
  4493. rv = textToSubURI->UnEscapeURIForUI(charset, spec,
  4494. formatStrs[formatStrCount]);
  4495. }
  4496. } else {
  4497. spec.Assign('?');
  4498. }
  4499. if (NS_FAILED(rv)) {
  4500. CopyUTF8toUTF16(spec, formatStrs[formatStrCount]);
  4501. }
  4502. rv = NS_OK;
  4503. ++formatStrCount;
  4504. const char16_t* strs[kMaxFormatStrArgs];
  4505. for (uint32_t i = 0; i < formatStrCount; i++) {
  4506. strs[i] = formatStrs[i].get();
  4507. }
  4508. nsXPIDLString str;
  4509. rv = stringBundle->FormatStringFromName(error.get(), strs, formatStrCount,
  4510. getter_Copies(str));
  4511. NS_ENSURE_SUCCESS(rv, rv);
  4512. messageStr.Assign(str.get());
  4513. }
  4514. // Display the error as a page or an alert prompt
  4515. NS_ENSURE_FALSE(messageStr.IsEmpty(), NS_ERROR_FAILURE);
  4516. if (NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) {
  4517. bool isSecureURI = false;
  4518. rv = aURI->SchemeIs("https", &isSecureURI);
  4519. if (NS_SUCCEEDED(rv) && isSecureURI) {
  4520. // Maybe TLS intolerant. Treat this as an SSL error.
  4521. error.AssignLiteral("nssFailure2");
  4522. }
  4523. }
  4524. if (UseErrorPages()) {
  4525. // Display an error page
  4526. nsresult loadedPage = LoadErrorPage(aURI, aURL, errorPage.get(),
  4527. error.get(), messageStr.get(),
  4528. cssClass.get(), aFailedChannel);
  4529. *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage);
  4530. } else {
  4531. // The prompter reqires that our private window has a document (or it
  4532. // asserts). Satisfy that assertion now since GetDoc will force
  4533. // creation of one if it hasn't already been created.
  4534. if (mScriptGlobal) {
  4535. Unused << mScriptGlobal->GetDoc();
  4536. }
  4537. // Display a message box
  4538. prompter->Alert(nullptr, messageStr.get());
  4539. }
  4540. return NS_OK;
  4541. }
  4542. #define PREF_SAFEBROWSING_ALLOWOVERRIDE "browser.safebrowsing.allowOverride"
  4543. NS_IMETHODIMP
  4544. nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
  4545. const char* aErrorPage,
  4546. const char16_t* aErrorType,
  4547. const char16_t* aDescription,
  4548. const char* aCSSClass,
  4549. nsIChannel* aFailedChannel)
  4550. {
  4551. #if defined(DEBUG)
  4552. if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)) {
  4553. nsAutoCString chanName;
  4554. if (aFailedChannel) {
  4555. aFailedChannel->GetName(chanName);
  4556. } else {
  4557. chanName.AssignLiteral("<no channel>");
  4558. }
  4559. MOZ_LOG(gDocShellLog, LogLevel::Debug,
  4560. ("nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n", this,
  4561. aURI->GetSpecOrDefault().get(), NS_ConvertUTF16toUTF8(aURL).get(),
  4562. chanName.get()));
  4563. }
  4564. #endif
  4565. mFailedChannel = aFailedChannel;
  4566. mFailedURI = aURI;
  4567. mFailedLoadType = mLoadType;
  4568. if (mLSHE) {
  4569. // Abandon mLSHE's BFCache entry and create a new one. This way, if
  4570. // we go back or forward to another SHEntry with the same doc
  4571. // identifier, the error page won't persist.
  4572. mLSHE->AbandonBFCacheEntry();
  4573. }
  4574. nsAutoCString url;
  4575. nsAutoCString charset;
  4576. if (aURI) {
  4577. nsresult rv = aURI->GetSpec(url);
  4578. NS_ENSURE_SUCCESS(rv, rv);
  4579. rv = aURI->GetOriginCharset(charset);
  4580. NS_ENSURE_SUCCESS(rv, rv);
  4581. } else if (aURL) {
  4582. CopyUTF16toUTF8(aURL, url);
  4583. } else {
  4584. return NS_ERROR_INVALID_POINTER;
  4585. }
  4586. // Create a URL to pass all the error information through to the page.
  4587. #undef SAFE_ESCAPE
  4588. #define SAFE_ESCAPE(output, input, params) \
  4589. if (NS_WARN_IF(!NS_Escape(input, output, params))) { \
  4590. return NS_ERROR_OUT_OF_MEMORY; \
  4591. }
  4592. nsCString escapedUrl, escapedCharset, escapedError, escapedDescription,
  4593. escapedCSSClass;
  4594. SAFE_ESCAPE(escapedUrl, url, url_Path);
  4595. SAFE_ESCAPE(escapedCharset, charset, url_Path);
  4596. SAFE_ESCAPE(escapedError, NS_ConvertUTF16toUTF8(aErrorType), url_Path);
  4597. SAFE_ESCAPE(escapedDescription,
  4598. NS_ConvertUTF16toUTF8(aDescription), url_Path);
  4599. if (aCSSClass) {
  4600. nsCString cssClass(aCSSClass);
  4601. SAFE_ESCAPE(escapedCSSClass, cssClass, url_Path);
  4602. }
  4603. nsCString errorPageUrl("about:");
  4604. errorPageUrl.AppendASCII(aErrorPage);
  4605. errorPageUrl.AppendLiteral("?e=");
  4606. errorPageUrl.AppendASCII(escapedError.get());
  4607. errorPageUrl.AppendLiteral("&u=");
  4608. errorPageUrl.AppendASCII(escapedUrl.get());
  4609. if ((strcmp(aErrorPage, "blocked") == 0) &&
  4610. Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE, true)) {
  4611. errorPageUrl.AppendLiteral("&o=1");
  4612. }
  4613. if (!escapedCSSClass.IsEmpty()) {
  4614. errorPageUrl.AppendLiteral("&s=");
  4615. errorPageUrl.AppendASCII(escapedCSSClass.get());
  4616. }
  4617. errorPageUrl.AppendLiteral("&c=");
  4618. errorPageUrl.AppendASCII(escapedCharset.get());
  4619. nsAutoCString frameType(FrameTypeToString(mFrameType));
  4620. errorPageUrl.AppendLiteral("&f=");
  4621. errorPageUrl.AppendASCII(frameType.get());
  4622. // Append the manifest URL if the error comes from an app.
  4623. nsString manifestURL;
  4624. nsresult rv = GetAppManifestURL(manifestURL);
  4625. if (manifestURL.Length() > 0) {
  4626. nsCString manifestParam;
  4627. SAFE_ESCAPE(manifestParam, NS_ConvertUTF16toUTF8(manifestURL), url_Path);
  4628. errorPageUrl.AppendLiteral("&m=");
  4629. errorPageUrl.AppendASCII(manifestParam.get());
  4630. }
  4631. nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID);
  4632. int32_t cpsState;
  4633. if (cps && NS_SUCCEEDED(cps->GetState(&cpsState)) &&
  4634. cpsState == nsICaptivePortalService::LOCKED_PORTAL) {
  4635. errorPageUrl.AppendLiteral("&captive=true");
  4636. }
  4637. // netError.xhtml's getDescription only handles the "d" parameter at the
  4638. // end of the URL, so append it last.
  4639. errorPageUrl.AppendLiteral("&d=");
  4640. errorPageUrl.AppendASCII(escapedDescription.get());
  4641. nsCOMPtr<nsIURI> errorPageURI;
  4642. rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
  4643. NS_ENSURE_SUCCESS(rv, rv);
  4644. return InternalLoad(errorPageURI, nullptr, false, false,
  4645. nullptr, mozilla::net::RP_Default,
  4646. nsContentUtils::GetSystemPrincipal(), nullptr,
  4647. INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
  4648. nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
  4649. nullptr, true, NullString(), this, nullptr, nullptr,
  4650. nullptr);
  4651. }
  4652. bool
  4653. nsDocShell::IsReloadFlooding()
  4654. {
  4655. if (mReloadFloodGuardCount > kReloadLimit) {
  4656. TimeStamp now = TimeStamp::Now();
  4657. if (now - mReloadFloodGuardUpdated > TimeDuration::FromSeconds(kReloadTimeSecs)) {
  4658. mReloadFloodGuardCount = 0;
  4659. mReloadFloodGuardUpdated = now;
  4660. mReloadFloodGuardReported = false;
  4661. return false;
  4662. }
  4663. return true;
  4664. }
  4665. mReloadFloodGuardCount++;
  4666. return false;
  4667. }
  4668. NS_IMETHODIMP
  4669. nsDocShell::Reload(uint32_t aReloadFlags)
  4670. {
  4671. if (!IsNavigationAllowed()) {
  4672. return NS_OK; // JS may not handle returning of an error code
  4673. }
  4674. nsresult rv;
  4675. NS_ASSERTION(((aReloadFlags & 0xf) == 0),
  4676. "Reload command not updated to use load flags!");
  4677. NS_ASSERTION((aReloadFlags & EXTRA_LOAD_FLAGS) == 0,
  4678. "Don't pass these flags to Reload");
  4679. uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags);
  4680. NS_ENSURE_TRUE(IsValidLoadType(loadType), NS_ERROR_INVALID_ARG);
  4681. // Send notifications to the HistoryListener if any, about the impending
  4682. // reload
  4683. nsCOMPtr<nsISHistory> rootSH;
  4684. rv = GetRootSessionHistory(getter_AddRefs(rootSH));
  4685. nsCOMPtr<nsISHistoryInternal> shistInt(do_QueryInterface(rootSH));
  4686. bool canReload = true;
  4687. if (rootSH) {
  4688. shistInt->NotifyOnHistoryReload(mCurrentURI, aReloadFlags, &canReload);
  4689. }
  4690. // If we're being flooded with reload requests, we should abort early
  4691. // from the reload logic.
  4692. if (IsReloadFlooding()) {
  4693. // Report a warning to the console to tell developers why their reload
  4694. // failed.
  4695. // Do this only if not yet marked reported so we only report it once per
  4696. // flood interval.
  4697. if (!mReloadFloodGuardReported) {
  4698. #if 0
  4699. nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
  4700. NS_LITERAL_CSTRING("Reload"),
  4701. GetDocument(),
  4702. nsContentUtils::eDOM_PROPERTIES,
  4703. "ReloadFloodingPrevented");
  4704. #endif
  4705. mReloadFloodGuardReported = true;
  4706. }
  4707. return NS_OK;
  4708. }
  4709. if (!canReload) {
  4710. return NS_OK;
  4711. }
  4712. /* If you change this part of code, make sure bug 45297 does not re-occur */
  4713. if (mOSHE) {
  4714. rv = LoadHistoryEntry(mOSHE, loadType);
  4715. } else if (mLSHE) { // In case a reload happened before the current load is done
  4716. rv = LoadHistoryEntry(mLSHE, loadType);
  4717. } else {
  4718. nsCOMPtr<nsIDocument> doc(GetDocument());
  4719. if (!doc) {
  4720. return NS_OK;
  4721. }
  4722. // Do not inherit owner from document
  4723. uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
  4724. nsAutoString srcdoc;
  4725. nsCOMPtr<nsIURI> baseURI;
  4726. nsCOMPtr<nsIURI> originalURI;
  4727. bool loadReplace = false;
  4728. nsIPrincipal* triggeringPrincipal = doc->NodePrincipal();
  4729. nsAutoString contentTypeHint;
  4730. doc->GetContentType(contentTypeHint);
  4731. if (doc->IsSrcdocDocument()) {
  4732. doc->GetSrcdocData(srcdoc);
  4733. flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
  4734. baseURI = doc->GetBaseURI();
  4735. }
  4736. nsCOMPtr<nsIChannel> chan = doc->GetChannel();
  4737. if (chan) {
  4738. uint32_t loadFlags;
  4739. chan->GetLoadFlags(&loadFlags);
  4740. loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
  4741. nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
  4742. if (httpChan) {
  4743. httpChan->GetOriginalURI(getter_AddRefs(originalURI));
  4744. }
  4745. }
  4746. MOZ_ASSERT(triggeringPrincipal, "Need a valid triggeringPrincipal");
  4747. // Stack variables to ensure changes to the member variables don't affect to
  4748. // the call.
  4749. nsCOMPtr<nsIURI> currentURI = mCurrentURI;
  4750. nsCOMPtr<nsIURI> referrerURI = mReferrerURI;
  4751. uint32_t referrerPolicy = mReferrerPolicy;
  4752. rv = InternalLoad(currentURI,
  4753. originalURI,
  4754. loadReplace,
  4755. false, // Is from processing frame attributes
  4756. referrerURI,
  4757. referrerPolicy,
  4758. triggeringPrincipal,
  4759. triggeringPrincipal,
  4760. flags,
  4761. EmptyString(), // No window target
  4762. NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
  4763. NullString(), // No forced download
  4764. nullptr, // No post data
  4765. nullptr, // No headers data
  4766. loadType, // Load type
  4767. nullptr, // No SHEntry
  4768. true,
  4769. srcdoc, // srcdoc argument for iframe
  4770. this, // For reloads we are the source
  4771. baseURI,
  4772. nullptr, // No nsIDocShell
  4773. nullptr); // No nsIRequest
  4774. }
  4775. return rv;
  4776. }
  4777. NS_IMETHODIMP
  4778. nsDocShell::Stop(uint32_t aStopFlags)
  4779. {
  4780. // Revoke any pending event related to content viewer restoration
  4781. mRestorePresentationEvent.Revoke();
  4782. if (mLoadType == LOAD_ERROR_PAGE) {
  4783. if (mLSHE) {
  4784. // Since error page loads never unset mLSHE, do so now
  4785. SetHistoryEntry(&mOSHE, mLSHE);
  4786. SetHistoryEntry(&mLSHE, nullptr);
  4787. }
  4788. mFailedChannel = nullptr;
  4789. mFailedURI = nullptr;
  4790. }
  4791. if (nsIWebNavigation::STOP_CONTENT & aStopFlags) {
  4792. // Stop the document loading and animations
  4793. if (mContentViewer) {
  4794. nsCOMPtr<nsIContentViewer> cv = mContentViewer;
  4795. cv->Stop();
  4796. }
  4797. } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
  4798. // Stop the document loading only
  4799. if (mContentViewer) {
  4800. RefPtr<nsIDocument> doc = mContentViewer->GetDocument();
  4801. if (doc) {
  4802. doc->StopDocumentLoad();
  4803. }
  4804. }
  4805. }
  4806. if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
  4807. // Suspend any timers that were set for this loader. We'll clear
  4808. // them out for good in CreateContentViewer.
  4809. if (mRefreshURIList) {
  4810. SuspendRefreshURIs();
  4811. mSavedRefreshURIList.swap(mRefreshURIList);
  4812. mRefreshURIList = nullptr;
  4813. }
  4814. // XXXbz We could also pass |this| to nsIURILoader::Stop. That will
  4815. // just call Stop() on us as an nsIDocumentLoader... We need fewer
  4816. // redundant apis!
  4817. Stop();
  4818. }
  4819. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  4820. while (iter.HasMore()) {
  4821. nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(iter.GetNext()));
  4822. if (shellAsNav) {
  4823. shellAsNav->Stop(aStopFlags);
  4824. }
  4825. }
  4826. return NS_OK;
  4827. }
  4828. NS_IMETHODIMP
  4829. nsDocShell::GetDocument(nsIDOMDocument** aDocument)
  4830. {
  4831. NS_ENSURE_ARG_POINTER(aDocument);
  4832. NS_ENSURE_SUCCESS(EnsureContentViewer(), NS_ERROR_FAILURE);
  4833. return mContentViewer->GetDOMDocument(aDocument);
  4834. }
  4835. NS_IMETHODIMP
  4836. nsDocShell::GetCurrentURI(nsIURI** aURI)
  4837. {
  4838. NS_ENSURE_ARG_POINTER(aURI);
  4839. if (mCurrentURI) {
  4840. return NS_EnsureSafeToReturn(mCurrentURI, aURI);
  4841. }
  4842. *aURI = nullptr;
  4843. return NS_OK;
  4844. }
  4845. NS_IMETHODIMP
  4846. nsDocShell::GetReferringURI(nsIURI** aURI)
  4847. {
  4848. NS_ENSURE_ARG_POINTER(aURI);
  4849. *aURI = mReferrerURI;
  4850. NS_IF_ADDREF(*aURI);
  4851. return NS_OK;
  4852. }
  4853. NS_IMETHODIMP
  4854. nsDocShell::SetSessionHistory(nsISHistory* aSessionHistory)
  4855. {
  4856. NS_ENSURE_TRUE(aSessionHistory, NS_ERROR_FAILURE);
  4857. // make sure that we are the root docshell and
  4858. // set a handle to root docshell in SH.
  4859. nsCOMPtr<nsIDocShellTreeItem> root;
  4860. /* Get the root docshell. If *this* is the root docshell
  4861. * then save a handle to *this* in SH. SH needs it to do
  4862. * traversions thro' its entries
  4863. */
  4864. GetSameTypeRootTreeItem(getter_AddRefs(root));
  4865. NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
  4866. if (root.get() == static_cast<nsIDocShellTreeItem*>(this)) {
  4867. mSessionHistory = aSessionHistory;
  4868. nsCOMPtr<nsISHistoryInternal> shPrivate =
  4869. do_QueryInterface(mSessionHistory);
  4870. NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE);
  4871. shPrivate->SetRootDocShell(this);
  4872. return NS_OK;
  4873. }
  4874. return NS_ERROR_FAILURE;
  4875. }
  4876. NS_IMETHODIMP
  4877. nsDocShell::GetSessionHistory(nsISHistory** aSessionHistory)
  4878. {
  4879. NS_ENSURE_ARG_POINTER(aSessionHistory);
  4880. *aSessionHistory = mSessionHistory;
  4881. NS_IF_ADDREF(*aSessionHistory);
  4882. return NS_OK;
  4883. }
  4884. //*****************************************************************************
  4885. // nsDocShell::nsIWebPageDescriptor
  4886. //*****************************************************************************
  4887. NS_IMETHODIMP
  4888. nsDocShell::LoadPage(nsISupports* aPageDescriptor, uint32_t aDisplayType)
  4889. {
  4890. nsCOMPtr<nsISHEntry> shEntryIn(do_QueryInterface(aPageDescriptor));
  4891. // Currently, the opaque 'page descriptor' is an nsISHEntry...
  4892. if (!shEntryIn) {
  4893. return NS_ERROR_INVALID_POINTER;
  4894. }
  4895. // Now clone shEntryIn, since we might end up modifying it later on, and we
  4896. // want a page descriptor to be reusable.
  4897. nsCOMPtr<nsISHEntry> shEntry;
  4898. nsresult rv = shEntryIn->Clone(getter_AddRefs(shEntry));
  4899. NS_ENSURE_SUCCESS(rv, rv);
  4900. // Give our cloned shEntry a new bfcache entry so this load is independent
  4901. // of all other loads. (This is important, in particular, for bugs 582795
  4902. // and 585298.)
  4903. rv = shEntry->AbandonBFCacheEntry();
  4904. NS_ENSURE_SUCCESS(rv, rv);
  4905. //
  4906. // load the page as view-source
  4907. //
  4908. if (nsIWebPageDescriptor::DISPLAY_AS_SOURCE == aDisplayType) {
  4909. nsCOMPtr<nsIURI> oldUri, newUri;
  4910. nsCString spec, newSpec;
  4911. // Create a new view-source URI and replace the original.
  4912. rv = shEntry->GetURI(getter_AddRefs(oldUri));
  4913. if (NS_FAILED(rv)) {
  4914. return rv;
  4915. }
  4916. oldUri->GetSpec(spec);
  4917. newSpec.AppendLiteral("view-source:");
  4918. newSpec.Append(spec);
  4919. rv = NS_NewURI(getter_AddRefs(newUri), newSpec);
  4920. if (NS_FAILED(rv)) {
  4921. return rv;
  4922. }
  4923. shEntry->SetURI(newUri);
  4924. shEntry->SetOriginalURI(nullptr);
  4925. // shEntry's current triggering principal is whoever loaded that page initially.
  4926. // But now we're doing another load of the page, via an API that is only exposed
  4927. // to system code. The triggering principal for this load should be the system
  4928. // principal.
  4929. shEntry->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
  4930. }
  4931. rv = LoadHistoryEntry(shEntry, LOAD_HISTORY);
  4932. return rv;
  4933. }
  4934. NS_IMETHODIMP
  4935. nsDocShell::GetCurrentDescriptor(nsISupports** aPageDescriptor)
  4936. {
  4937. NS_PRECONDITION(aPageDescriptor, "Null out param?");
  4938. *aPageDescriptor = nullptr;
  4939. nsISHEntry* src = mOSHE ? mOSHE : mLSHE;
  4940. if (src) {
  4941. nsCOMPtr<nsISHEntry> dest;
  4942. nsresult rv = src->Clone(getter_AddRefs(dest));
  4943. if (NS_FAILED(rv)) {
  4944. return rv;
  4945. }
  4946. // null out inappropriate cloned attributes...
  4947. dest->SetParent(nullptr);
  4948. dest->SetIsSubFrame(false);
  4949. return CallQueryInterface(dest, aPageDescriptor);
  4950. }
  4951. return NS_ERROR_NOT_AVAILABLE;
  4952. }
  4953. //*****************************************************************************
  4954. // nsDocShell::nsIBaseWindow
  4955. //*****************************************************************************
  4956. NS_IMETHODIMP
  4957. nsDocShell::InitWindow(nativeWindow aParentNativeWindow,
  4958. nsIWidget* aParentWidget, int32_t aX, int32_t aY,
  4959. int32_t aWidth, int32_t aHeight)
  4960. {
  4961. SetParentWidget(aParentWidget);
  4962. SetPositionAndSize(aX, aY, aWidth, aHeight, 0);
  4963. return NS_OK;
  4964. }
  4965. NS_IMETHODIMP
  4966. nsDocShell::Create()
  4967. {
  4968. if (mCreated) {
  4969. // We've already been created
  4970. return NS_OK;
  4971. }
  4972. NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,
  4973. "Unexpected item type in docshell");
  4974. NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
  4975. mCreated = true;
  4976. if (gValidateOrigin == 0xffffffff) {
  4977. // Check pref to see if we should prevent frameset spoofing
  4978. gValidateOrigin =
  4979. Preferences::GetBool("browser.frame.validate_origin", true);
  4980. }
  4981. // Should we use XUL error pages instead of alerts if possible?
  4982. mUseErrorPages =
  4983. Preferences::GetBool("browser.xul.error_pages.enabled", mUseErrorPages);
  4984. if (!gAddedPreferencesVarCache) {
  4985. Preferences::AddBoolVarCache(&sUseErrorPages,
  4986. "browser.xul.error_pages.enabled",
  4987. mUseErrorPages);
  4988. gAddedPreferencesVarCache = true;
  4989. }
  4990. mDisableMetaRefreshWhenInactive =
  4991. Preferences::GetBool("browser.meta_refresh_when_inactive.disabled",
  4992. mDisableMetaRefreshWhenInactive);
  4993. mDeviceSizeIsPageSize =
  4994. Preferences::GetBool("docshell.device_size_is_page_size",
  4995. mDeviceSizeIsPageSize);
  4996. nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
  4997. if (serv) {
  4998. const char* msg = mItemType == typeContent ?
  4999. NS_WEBNAVIGATION_CREATE : NS_CHROME_WEBNAVIGATION_CREATE;
  5000. serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
  5001. }
  5002. return NS_OK;
  5003. }
  5004. NS_IMETHODIMP
  5005. nsDocShell::Destroy()
  5006. {
  5007. NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,
  5008. "Unexpected item type in docshell");
  5009. if (!mIsBeingDestroyed) {
  5010. nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
  5011. if (serv) {
  5012. const char* msg = mItemType == typeContent ?
  5013. NS_WEBNAVIGATION_DESTROY : NS_CHROME_WEBNAVIGATION_DESTROY;
  5014. serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
  5015. }
  5016. }
  5017. mIsBeingDestroyed = true;
  5018. // Make sure we don't record profile timeline markers anymore
  5019. SetRecordProfileTimelineMarkers(false);
  5020. // Remove our pref observers
  5021. if (mObserveErrorPages) {
  5022. mObserveErrorPages = false;
  5023. }
  5024. // Make sure to blow away our mLoadingURI just in case. No loads
  5025. // from inside this pagehide.
  5026. mLoadingURI = nullptr;
  5027. // Fire unload event before we blow anything away.
  5028. (void)FirePageHideNotification(true);
  5029. // Clear pointers to any detached nsEditorData that's lying
  5030. // around in shistory entries. Breaks cycle. See bug 430921.
  5031. if (mOSHE) {
  5032. mOSHE->SetEditorData(nullptr);
  5033. }
  5034. if (mLSHE) {
  5035. mLSHE->SetEditorData(nullptr);
  5036. }
  5037. // Note: mContentListener can be null if Init() failed and we're being
  5038. // called from the destructor.
  5039. if (mContentListener) {
  5040. mContentListener->DropDocShellReference();
  5041. mContentListener->SetParentContentListener(nullptr);
  5042. // Note that we do NOT set mContentListener to null here; that
  5043. // way if someone tries to do a load in us after this point
  5044. // the nsDSURIContentListener will block it. All of which
  5045. // means that we should do this before calling Stop(), of
  5046. // course.
  5047. }
  5048. // Stop any URLs that are currently being loaded...
  5049. Stop(nsIWebNavigation::STOP_ALL);
  5050. mEditorData = nullptr;
  5051. mTransferableHookData = nullptr;
  5052. // Save the state of the current document, before destroying the window.
  5053. // This is needed to capture the state of a frameset when the new document
  5054. // causes the frameset to be destroyed...
  5055. PersistLayoutHistoryState();
  5056. // Remove this docshell from its parent's child list
  5057. nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem =
  5058. do_QueryInterface(GetAsSupports(mParent));
  5059. if (docShellParentAsItem) {
  5060. docShellParentAsItem->RemoveChild(this);
  5061. }
  5062. if (mContentViewer) {
  5063. mContentViewer->Close(nullptr);
  5064. mContentViewer->Destroy();
  5065. mContentViewer = nullptr;
  5066. }
  5067. nsDocLoader::Destroy();
  5068. mParentWidget = nullptr;
  5069. mCurrentURI = nullptr;
  5070. if (mScriptGlobal) {
  5071. mScriptGlobal->DetachFromDocShell();
  5072. mScriptGlobal = nullptr;
  5073. }
  5074. if (mSessionHistory) {
  5075. // We want to destroy these content viewers now rather than
  5076. // letting their destruction wait for the session history
  5077. // entries to get garbage collected. (Bug 488394)
  5078. nsCOMPtr<nsISHistoryInternal> shPrivate =
  5079. do_QueryInterface(mSessionHistory);
  5080. if (shPrivate) {
  5081. shPrivate->EvictAllContentViewers();
  5082. }
  5083. mSessionHistory = nullptr;
  5084. }
  5085. SetTreeOwner(nullptr);
  5086. mOnePermittedSandboxedNavigator = nullptr;
  5087. // required to break ref cycle
  5088. mSecurityUI = nullptr;
  5089. // Cancel any timers that were set for this docshell; this is needed
  5090. // to break the cycle between us and the timers.
  5091. CancelRefreshURITimers();
  5092. if (UsePrivateBrowsing()) {
  5093. mPrivateBrowsingId = 0;
  5094. mOriginAttributes.SyncAttributesWithPrivateBrowsing(false);
  5095. if (mAffectPrivateSessionLifetime) {
  5096. DecreasePrivateDocShellCount();
  5097. }
  5098. }
  5099. return NS_OK;
  5100. }
  5101. NS_IMETHODIMP
  5102. nsDocShell::GetUnscaledDevicePixelsPerCSSPixel(double* aScale)
  5103. {
  5104. if (mParentWidget) {
  5105. *aScale = mParentWidget->GetDefaultScale().scale;
  5106. return NS_OK;
  5107. }
  5108. nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
  5109. if (ownerWindow) {
  5110. return ownerWindow->GetUnscaledDevicePixelsPerCSSPixel(aScale);
  5111. }
  5112. *aScale = 1.0;
  5113. return NS_OK;
  5114. }
  5115. NS_IMETHODIMP
  5116. nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale)
  5117. {
  5118. if (mParentWidget) {
  5119. *aScale = mParentWidget->GetDesktopToDeviceScale().scale;
  5120. return NS_OK;
  5121. }
  5122. nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
  5123. if (ownerWindow) {
  5124. return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale);
  5125. }
  5126. *aScale = 1.0;
  5127. return NS_OK;
  5128. }
  5129. NS_IMETHODIMP
  5130. nsDocShell::SetPosition(int32_t aX, int32_t aY)
  5131. {
  5132. mBounds.x = aX;
  5133. mBounds.y = aY;
  5134. if (mContentViewer) {
  5135. NS_ENSURE_SUCCESS(mContentViewer->Move(aX, aY), NS_ERROR_FAILURE);
  5136. }
  5137. return NS_OK;
  5138. }
  5139. NS_IMETHODIMP
  5140. nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY)
  5141. {
  5142. nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
  5143. if (ownerWindow) {
  5144. return ownerWindow->SetPositionDesktopPix(aX, aY);
  5145. }
  5146. double scale = 1.0;
  5147. GetDevicePixelsPerDesktopPixel(&scale);
  5148. return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
  5149. }
  5150. NS_IMETHODIMP
  5151. nsDocShell::GetPosition(int32_t* aX, int32_t* aY)
  5152. {
  5153. return GetPositionAndSize(aX, aY, nullptr, nullptr);
  5154. }
  5155. NS_IMETHODIMP
  5156. nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint)
  5157. {
  5158. int32_t x = 0, y = 0;
  5159. GetPosition(&x, &y);
  5160. return SetPositionAndSize(x, y, aWidth, aHeight,
  5161. aRepaint ? nsIBaseWindow::eRepaint : 0);
  5162. }
  5163. NS_IMETHODIMP
  5164. nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight)
  5165. {
  5166. return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight);
  5167. }
  5168. NS_IMETHODIMP
  5169. nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth,
  5170. int32_t aHeight, uint32_t aFlags)
  5171. {
  5172. mBounds.x = aX;
  5173. mBounds.y = aY;
  5174. mBounds.width = aWidth;
  5175. mBounds.height = aHeight;
  5176. // Hold strong ref, since SetBounds can make us null out mContentViewer
  5177. nsCOMPtr<nsIContentViewer> viewer = mContentViewer;
  5178. if (viewer) {
  5179. uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize) ?
  5180. nsIContentViewer::eDelayResize : 0;
  5181. // XXX Border figured in here or is that handled elsewhere?
  5182. nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags);
  5183. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  5184. }
  5185. return NS_OK;
  5186. }
  5187. NS_IMETHODIMP
  5188. nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
  5189. int32_t* aHeight)
  5190. {
  5191. if (mParentWidget) {
  5192. // ensure size is up-to-date if window has changed resolution
  5193. LayoutDeviceIntRect r = mParentWidget->GetClientBounds();
  5194. SetPositionAndSize(mBounds.x, mBounds.y, r.width, r.height, 0);
  5195. }
  5196. // We should really consider just getting this information from
  5197. // our window instead of duplicating the storage and code...
  5198. if (aWidth || aHeight) {
  5199. // Caller wants to know our size; make sure to give them up to
  5200. // date information.
  5201. nsCOMPtr<nsIDocument> doc(do_GetInterface(GetAsSupports(mParent)));
  5202. if (doc) {
  5203. doc->FlushPendingNotifications(Flush_Layout);
  5204. }
  5205. }
  5206. DoGetPositionAndSize(aX, aY, aWidth, aHeight);
  5207. return NS_OK;
  5208. }
  5209. void
  5210. nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
  5211. int32_t* aHeight)
  5212. {
  5213. if (aX) {
  5214. *aX = mBounds.x;
  5215. }
  5216. if (aY) {
  5217. *aY = mBounds.y;
  5218. }
  5219. if (aWidth) {
  5220. *aWidth = mBounds.width;
  5221. }
  5222. if (aHeight) {
  5223. *aHeight = mBounds.height;
  5224. }
  5225. }
  5226. NS_IMETHODIMP
  5227. nsDocShell::Repaint(bool aForce)
  5228. {
  5229. nsCOMPtr<nsIPresShell> presShell = GetPresShell();
  5230. NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
  5231. nsViewManager* viewManager = presShell->GetViewManager();
  5232. NS_ENSURE_TRUE(viewManager, NS_ERROR_FAILURE);
  5233. viewManager->InvalidateAllViews();
  5234. return NS_OK;
  5235. }
  5236. NS_IMETHODIMP
  5237. nsDocShell::GetParentWidget(nsIWidget** aParentWidget)
  5238. {
  5239. NS_ENSURE_ARG_POINTER(aParentWidget);
  5240. *aParentWidget = mParentWidget;
  5241. NS_IF_ADDREF(*aParentWidget);
  5242. return NS_OK;
  5243. }
  5244. NS_IMETHODIMP
  5245. nsDocShell::SetParentWidget(nsIWidget* aParentWidget)
  5246. {
  5247. mParentWidget = aParentWidget;
  5248. return NS_OK;
  5249. }
  5250. NS_IMETHODIMP
  5251. nsDocShell::GetParentNativeWindow(nativeWindow* aParentNativeWindow)
  5252. {
  5253. NS_ENSURE_ARG_POINTER(aParentNativeWindow);
  5254. if (mParentWidget) {
  5255. *aParentNativeWindow = mParentWidget->GetNativeData(NS_NATIVE_WIDGET);
  5256. } else {
  5257. *aParentNativeWindow = nullptr;
  5258. }
  5259. return NS_OK;
  5260. }
  5261. NS_IMETHODIMP
  5262. nsDocShell::SetParentNativeWindow(nativeWindow aParentNativeWindow)
  5263. {
  5264. return NS_ERROR_NOT_IMPLEMENTED;
  5265. }
  5266. NS_IMETHODIMP
  5267. nsDocShell::GetNativeHandle(nsAString& aNativeHandle)
  5268. {
  5269. // the nativeHandle should be accessed from nsIXULWindow
  5270. return NS_ERROR_NOT_IMPLEMENTED;
  5271. }
  5272. NS_IMETHODIMP
  5273. nsDocShell::GetVisibility(bool* aVisibility)
  5274. {
  5275. NS_ENSURE_ARG_POINTER(aVisibility);
  5276. *aVisibility = false;
  5277. if (!mContentViewer) {
  5278. return NS_OK;
  5279. }
  5280. nsCOMPtr<nsIPresShell> presShell = GetPresShell();
  5281. if (!presShell) {
  5282. return NS_OK;
  5283. }
  5284. // get the view manager
  5285. nsViewManager* vm = presShell->GetViewManager();
  5286. NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE);
  5287. // get the root view
  5288. nsView* view = vm->GetRootView(); // views are not ref counted
  5289. NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
  5290. // if our root view is hidden, we are not visible
  5291. if (view->GetVisibility() == nsViewVisibility_kHide) {
  5292. return NS_OK;
  5293. }
  5294. // otherwise, we must walk up the document and view trees checking
  5295. // for a hidden view, unless we're an off screen browser, which
  5296. // would make this test meaningless.
  5297. RefPtr<nsDocShell> docShell = this;
  5298. RefPtr<nsDocShell> parentItem = docShell->GetParentDocshell();
  5299. while (parentItem) {
  5300. presShell = docShell->GetPresShell();
  5301. nsCOMPtr<nsIPresShell> pPresShell = parentItem->GetPresShell();
  5302. // Null-check for crash in bug 267804
  5303. if (!pPresShell) {
  5304. NS_NOTREACHED("parent docshell has null pres shell");
  5305. return NS_OK;
  5306. }
  5307. vm = presShell->GetViewManager();
  5308. if (vm) {
  5309. view = vm->GetRootView();
  5310. }
  5311. if (view) {
  5312. view = view->GetParent(); // anonymous inner view
  5313. if (view) {
  5314. view = view->GetParent(); // subdocumentframe's view
  5315. }
  5316. }
  5317. nsIFrame* frame = view ? view->GetFrame() : nullptr;
  5318. bool isDocShellOffScreen = false;
  5319. docShell->GetIsOffScreenBrowser(&isDocShellOffScreen);
  5320. if (frame &&
  5321. !frame->IsVisibleConsideringAncestors(
  5322. nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) &&
  5323. !isDocShellOffScreen) {
  5324. return NS_OK;
  5325. }
  5326. docShell = parentItem;
  5327. parentItem = docShell->GetParentDocshell();
  5328. }
  5329. nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
  5330. if (!treeOwnerAsWin) {
  5331. *aVisibility = true;
  5332. return NS_OK;
  5333. }
  5334. // Check with the tree owner as well to give embedders a chance to
  5335. // expose visibility as well.
  5336. return treeOwnerAsWin->GetVisibility(aVisibility);
  5337. }
  5338. NS_IMETHODIMP
  5339. nsDocShell::SetIsOffScreenBrowser(bool aIsOffScreen)
  5340. {
  5341. mIsOffScreenBrowser = aIsOffScreen;
  5342. return NS_OK;
  5343. }
  5344. NS_IMETHODIMP
  5345. nsDocShell::GetIsOffScreenBrowser(bool* aIsOffScreen)
  5346. {
  5347. *aIsOffScreen = mIsOffScreenBrowser;
  5348. return NS_OK;
  5349. }
  5350. NS_IMETHODIMP
  5351. nsDocShell::SetIsActive(bool aIsActive)
  5352. {
  5353. // We disallow setting active on chrome docshells.
  5354. if (mItemType == nsIDocShellTreeItem::typeChrome) {
  5355. return NS_ERROR_INVALID_ARG;
  5356. }
  5357. // Keep track ourselves.
  5358. mIsActive = aIsActive;
  5359. // Clear prerender flag if necessary.
  5360. mIsPrerendered &= !aIsActive;
  5361. // Tell the PresShell about it.
  5362. nsCOMPtr<nsIPresShell> pshell = GetPresShell();
  5363. if (pshell) {
  5364. pshell->SetIsActive(aIsActive);
  5365. }
  5366. // Tell the window about it
  5367. if (mScriptGlobal) {
  5368. mScriptGlobal->SetIsBackground(!aIsActive);
  5369. if (nsCOMPtr<nsIDocument> doc = mScriptGlobal->GetExtantDoc()) {
  5370. // Update orientation when the top-level browsing context becomes active.
  5371. // We make an exception for apps because they currently rely on
  5372. // orientation locks persisting across browsing contexts.
  5373. if (aIsActive && !GetIsApp()) {
  5374. nsCOMPtr<nsIDocShellTreeItem> parent;
  5375. GetSameTypeParent(getter_AddRefs(parent));
  5376. if (!parent) {
  5377. // We only care about the top-level browsing context.
  5378. uint16_t orientation = OrientationLock();
  5379. ScreenOrientation::UpdateActiveOrientationLock(orientation);
  5380. }
  5381. }
  5382. doc->PostVisibilityUpdateEvent();
  5383. }
  5384. }
  5385. // Tell the nsDOMNavigationTiming about it
  5386. RefPtr<nsDOMNavigationTiming> timing = mTiming;
  5387. if (!timing && mContentViewer) {
  5388. nsIDocument* doc = mContentViewer->GetDocument();
  5389. if (doc) {
  5390. timing = doc->GetNavigationTiming();
  5391. }
  5392. }
  5393. if (timing) {
  5394. timing->NotifyDocShellStateChanged(
  5395. aIsActive ? nsDOMNavigationTiming::DocShellState::eActive
  5396. : nsDOMNavigationTiming::DocShellState::eInactive);
  5397. }
  5398. // Recursively tell all of our children, but don't tell <iframe mozbrowser>
  5399. // children; they handle their state separately.
  5400. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  5401. while (iter.HasMore()) {
  5402. nsCOMPtr<nsIDocShell> docshell = do_QueryObject(iter.GetNext());
  5403. if (!docshell) {
  5404. continue;
  5405. }
  5406. if (!docshell->GetIsMozBrowserOrApp()) {
  5407. docshell->SetIsActive(aIsActive);
  5408. }
  5409. }
  5410. // Restart or stop meta refresh timers if necessary
  5411. if (mDisableMetaRefreshWhenInactive) {
  5412. if (mIsActive) {
  5413. ResumeRefreshURIs();
  5414. } else {
  5415. SuspendRefreshURIs();
  5416. }
  5417. }
  5418. return NS_OK;
  5419. }
  5420. NS_IMETHODIMP
  5421. nsDocShell::GetIsActive(bool* aIsActive)
  5422. {
  5423. *aIsActive = mIsActive;
  5424. return NS_OK;
  5425. }
  5426. NS_IMETHODIMP
  5427. nsDocShell::SetIsPrerendered()
  5428. {
  5429. MOZ_ASSERT(!mIsPrerendered,
  5430. "SetIsPrerendered() called on already prerendered docshell");
  5431. SetIsActive(false);
  5432. mIsPrerendered = true;
  5433. return NS_OK;
  5434. }
  5435. NS_IMETHODIMP
  5436. nsDocShell::GetIsPrerendered(bool* aIsPrerendered)
  5437. {
  5438. *aIsPrerendered = mIsPrerendered;
  5439. return NS_OK;
  5440. }
  5441. NS_IMETHODIMP
  5442. nsDocShell::SetIsAppTab(bool aIsAppTab)
  5443. {
  5444. mIsAppTab = aIsAppTab;
  5445. return NS_OK;
  5446. }
  5447. NS_IMETHODIMP
  5448. nsDocShell::GetIsAppTab(bool* aIsAppTab)
  5449. {
  5450. *aIsAppTab = mIsAppTab;
  5451. return NS_OK;
  5452. }
  5453. NS_IMETHODIMP
  5454. nsDocShell::SetSandboxFlags(uint32_t aSandboxFlags)
  5455. {
  5456. mSandboxFlags = aSandboxFlags;
  5457. return NS_OK;
  5458. }
  5459. NS_IMETHODIMP
  5460. nsDocShell::GetSandboxFlags(uint32_t* aSandboxFlags)
  5461. {
  5462. *aSandboxFlags = mSandboxFlags;
  5463. return NS_OK;
  5464. }
  5465. NS_IMETHODIMP
  5466. nsDocShell::SetOnePermittedSandboxedNavigator(nsIDocShell* aSandboxedNavigator)
  5467. {
  5468. if (mOnePermittedSandboxedNavigator) {
  5469. NS_ERROR("One Permitted Sandboxed Navigator should only be set once.");
  5470. return NS_OK;
  5471. }
  5472. mOnePermittedSandboxedNavigator = do_GetWeakReference(aSandboxedNavigator);
  5473. NS_ASSERTION(mOnePermittedSandboxedNavigator,
  5474. "One Permitted Sandboxed Navigator must support weak references.");
  5475. return NS_OK;
  5476. }
  5477. NS_IMETHODIMP
  5478. nsDocShell::GetOnePermittedSandboxedNavigator(nsIDocShell** aSandboxedNavigator)
  5479. {
  5480. NS_ENSURE_ARG_POINTER(aSandboxedNavigator);
  5481. nsCOMPtr<nsIDocShell> permittedNavigator =
  5482. do_QueryReferent(mOnePermittedSandboxedNavigator);
  5483. permittedNavigator.forget(aSandboxedNavigator);
  5484. return NS_OK;
  5485. }
  5486. NS_IMETHODIMP
  5487. nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags)
  5488. {
  5489. mDefaultLoadFlags = aDefaultLoadFlags;
  5490. // Tell the load group to set these flags all requests in the group
  5491. if (mLoadGroup) {
  5492. mLoadGroup->SetDefaultLoadFlags(aDefaultLoadFlags);
  5493. } else {
  5494. NS_WARNING("nsDocShell::SetDefaultLoadFlags has no loadGroup to propagate the flags to");
  5495. }
  5496. // Recursively tell all of our children. We *do not* skip
  5497. // <iframe mozbrowser> children - if someone sticks custom flags in this
  5498. // docShell then they too get the same flags.
  5499. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  5500. while (iter.HasMore()) {
  5501. nsCOMPtr<nsIDocShell> docshell = do_QueryObject(iter.GetNext());
  5502. if (!docshell) {
  5503. continue;
  5504. }
  5505. docshell->SetDefaultLoadFlags(aDefaultLoadFlags);
  5506. }
  5507. return NS_OK;
  5508. }
  5509. NS_IMETHODIMP
  5510. nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags)
  5511. {
  5512. *aDefaultLoadFlags = mDefaultLoadFlags;
  5513. return NS_OK;
  5514. }
  5515. NS_IMETHODIMP
  5516. nsDocShell::SetMixedContentChannel(nsIChannel* aMixedContentChannel)
  5517. {
  5518. #ifdef DEBUG
  5519. // if the channel is non-null
  5520. if (aMixedContentChannel) {
  5521. // Get the root docshell.
  5522. nsCOMPtr<nsIDocShellTreeItem> root;
  5523. GetSameTypeRootTreeItem(getter_AddRefs(root));
  5524. NS_WARNING_ASSERTION(root.get() == static_cast<nsIDocShellTreeItem*>(this),
  5525. "Setting mMixedContentChannel on a docshell that is "
  5526. "not the root docshell");
  5527. }
  5528. #endif
  5529. mMixedContentChannel = aMixedContentChannel;
  5530. return NS_OK;
  5531. }
  5532. NS_IMETHODIMP
  5533. nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel)
  5534. {
  5535. NS_ENSURE_ARG_POINTER(aFailedChannel);
  5536. nsIDocument* doc = GetDocument();
  5537. if (!doc) {
  5538. *aFailedChannel = nullptr;
  5539. return NS_OK;
  5540. }
  5541. NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel());
  5542. return NS_OK;
  5543. }
  5544. NS_IMETHODIMP
  5545. nsDocShell::GetMixedContentChannel(nsIChannel** aMixedContentChannel)
  5546. {
  5547. NS_ENSURE_ARG_POINTER(aMixedContentChannel);
  5548. NS_IF_ADDREF(*aMixedContentChannel = mMixedContentChannel);
  5549. return NS_OK;
  5550. }
  5551. NS_IMETHODIMP
  5552. nsDocShell::GetAllowMixedContentAndConnectionData(bool* aRootHasSecureConnection,
  5553. bool* aAllowMixedContent,
  5554. bool* aIsRootDocShell)
  5555. {
  5556. *aRootHasSecureConnection = true;
  5557. *aAllowMixedContent = false;
  5558. *aIsRootDocShell = false;
  5559. nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
  5560. GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
  5561. NS_ASSERTION(sameTypeRoot,
  5562. "No document shell root tree item from document shell tree item!");
  5563. *aIsRootDocShell =
  5564. sameTypeRoot.get() == static_cast<nsIDocShellTreeItem*>(this);
  5565. // now get the document from sameTypeRoot
  5566. nsCOMPtr<nsIDocument> rootDoc = sameTypeRoot->GetDocument();
  5567. if (rootDoc) {
  5568. nsCOMPtr<nsIPrincipal> rootPrincipal = rootDoc->NodePrincipal();
  5569. // For things with system principal (e.g. scratchpad) there is no uri
  5570. // aRootHasSecureConnection should be false.
  5571. nsCOMPtr<nsIURI> rootUri;
  5572. if (nsContentUtils::IsSystemPrincipal(rootPrincipal) ||
  5573. NS_FAILED(rootPrincipal->GetURI(getter_AddRefs(rootUri))) || !rootUri ||
  5574. NS_FAILED(rootUri->SchemeIs("https", aRootHasSecureConnection))) {
  5575. *aRootHasSecureConnection = false;
  5576. }
  5577. // Check the root doc's channel against the root docShell's
  5578. // mMixedContentChannel to see if they are the same. If they are the same,
  5579. // the user has overriden the block.
  5580. nsCOMPtr<nsIDocShell> rootDocShell = do_QueryInterface(sameTypeRoot);
  5581. nsCOMPtr<nsIChannel> mixedChannel;
  5582. rootDocShell->GetMixedContentChannel(getter_AddRefs(mixedChannel));
  5583. *aAllowMixedContent =
  5584. mixedChannel && (mixedChannel == rootDoc->GetChannel());
  5585. }
  5586. return NS_OK;
  5587. }
  5588. NS_IMETHODIMP
  5589. nsDocShell::SetVisibility(bool aVisibility)
  5590. {
  5591. // Show()/Hide() may change mContentViewer.
  5592. nsCOMPtr<nsIContentViewer> cv = mContentViewer;
  5593. if (!cv) {
  5594. return NS_OK;
  5595. }
  5596. if (aVisibility) {
  5597. cv->Show();
  5598. } else {
  5599. cv->Hide();
  5600. }
  5601. return NS_OK;
  5602. }
  5603. NS_IMETHODIMP
  5604. nsDocShell::GetEnabled(bool* aEnabled)
  5605. {
  5606. NS_ENSURE_ARG_POINTER(aEnabled);
  5607. *aEnabled = true;
  5608. return NS_ERROR_NOT_IMPLEMENTED;
  5609. }
  5610. NS_IMETHODIMP
  5611. nsDocShell::SetEnabled(bool aEnabled)
  5612. {
  5613. return NS_ERROR_NOT_IMPLEMENTED;
  5614. }
  5615. NS_IMETHODIMP
  5616. nsDocShell::SetFocus()
  5617. {
  5618. return NS_OK;
  5619. }
  5620. NS_IMETHODIMP
  5621. nsDocShell::GetMainWidget(nsIWidget** aMainWidget)
  5622. {
  5623. // We don't create our own widget, so simply return the parent one.
  5624. return GetParentWidget(aMainWidget);
  5625. }
  5626. NS_IMETHODIMP
  5627. nsDocShell::GetTitle(char16_t** aTitle)
  5628. {
  5629. NS_ENSURE_ARG_POINTER(aTitle);
  5630. *aTitle = ToNewUnicode(mTitle);
  5631. return NS_OK;
  5632. }
  5633. NS_IMETHODIMP
  5634. nsDocShell::SetTitle(const char16_t* aTitle)
  5635. {
  5636. // Store local title
  5637. mTitle = aTitle;
  5638. nsCOMPtr<nsIDocShellTreeItem> parent;
  5639. GetSameTypeParent(getter_AddRefs(parent));
  5640. // When title is set on the top object it should then be passed to the
  5641. // tree owner.
  5642. if (!parent) {
  5643. nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
  5644. if (treeOwnerAsWin) {
  5645. treeOwnerAsWin->SetTitle(aTitle);
  5646. }
  5647. }
  5648. AssertOriginAttributesMatchPrivateBrowsing();
  5649. if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE && mUseGlobalHistory &&
  5650. !UsePrivateBrowsing()) {
  5651. nsCOMPtr<IHistory> history = services::GetHistoryService();
  5652. if (history) {
  5653. history->SetURITitle(mCurrentURI, mTitle);
  5654. } else if (mGlobalHistory) {
  5655. mGlobalHistory->SetPageTitle(mCurrentURI, nsString(mTitle));
  5656. }
  5657. }
  5658. // Update SessionHistory with the document's title.
  5659. if (mOSHE && mLoadType != LOAD_BYPASS_HISTORY &&
  5660. mLoadType != LOAD_ERROR_PAGE) {
  5661. mOSHE->SetTitle(mTitle);
  5662. }
  5663. return NS_OK;
  5664. }
  5665. nsresult
  5666. nsDocShell::GetCurScrollPos(int32_t aScrollOrientation, int32_t* aCurPos)
  5667. {
  5668. NS_ENSURE_ARG_POINTER(aCurPos);
  5669. nsIScrollableFrame* sf = GetRootScrollFrame();
  5670. if (!sf) {
  5671. return NS_ERROR_FAILURE;
  5672. }
  5673. nsPoint pt = sf->GetScrollPosition();
  5674. switch (aScrollOrientation) {
  5675. case ScrollOrientation_X:
  5676. *aCurPos = pt.x;
  5677. return NS_OK;
  5678. case ScrollOrientation_Y:
  5679. *aCurPos = pt.y;
  5680. return NS_OK;
  5681. default:
  5682. NS_ENSURE_TRUE(false, NS_ERROR_INVALID_ARG);
  5683. }
  5684. }
  5685. nsresult
  5686. nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos,
  5687. int32_t aCurVerticalPos)
  5688. {
  5689. nsIScrollableFrame* sf = GetRootScrollFrame();
  5690. NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE);
  5691. sf->ScrollTo(nsPoint(aCurHorizontalPos, aCurVerticalPos),
  5692. nsIScrollableFrame::INSTANT);
  5693. return NS_OK;
  5694. }
  5695. //*****************************************************************************
  5696. // nsDocShell::nsIScrollable
  5697. //*****************************************************************************
  5698. NS_IMETHODIMP
  5699. nsDocShell::GetDefaultScrollbarPreferences(int32_t aScrollOrientation,
  5700. int32_t* aScrollbarPref)
  5701. {
  5702. NS_ENSURE_ARG_POINTER(aScrollbarPref);
  5703. switch (aScrollOrientation) {
  5704. case ScrollOrientation_X:
  5705. *aScrollbarPref = mDefaultScrollbarPref.x;
  5706. return NS_OK;
  5707. case ScrollOrientation_Y:
  5708. *aScrollbarPref = mDefaultScrollbarPref.y;
  5709. return NS_OK;
  5710. default:
  5711. NS_ENSURE_TRUE(false, NS_ERROR_INVALID_ARG);
  5712. }
  5713. return NS_ERROR_FAILURE;
  5714. }
  5715. NS_IMETHODIMP
  5716. nsDocShell::SetDefaultScrollbarPreferences(int32_t aScrollOrientation,
  5717. int32_t aScrollbarPref)
  5718. {
  5719. switch (aScrollOrientation) {
  5720. case ScrollOrientation_X:
  5721. mDefaultScrollbarPref.x = aScrollbarPref;
  5722. return NS_OK;
  5723. case ScrollOrientation_Y:
  5724. mDefaultScrollbarPref.y = aScrollbarPref;
  5725. return NS_OK;
  5726. default:
  5727. NS_ENSURE_TRUE(false, NS_ERROR_INVALID_ARG);
  5728. }
  5729. return NS_ERROR_FAILURE;
  5730. }
  5731. NS_IMETHODIMP
  5732. nsDocShell::GetScrollbarVisibility(bool* aVerticalVisible,
  5733. bool* aHorizontalVisible)
  5734. {
  5735. nsIScrollableFrame* sf = GetRootScrollFrame();
  5736. NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE);
  5737. uint32_t scrollbarVisibility = sf->GetScrollbarVisibility();
  5738. if (aVerticalVisible) {
  5739. *aVerticalVisible =
  5740. (scrollbarVisibility & nsIScrollableFrame::VERTICAL) != 0;
  5741. }
  5742. if (aHorizontalVisible) {
  5743. *aHorizontalVisible =
  5744. (scrollbarVisibility & nsIScrollableFrame::HORIZONTAL) != 0;
  5745. }
  5746. return NS_OK;
  5747. }
  5748. //*****************************************************************************
  5749. // nsDocShell::nsITextScroll
  5750. //*****************************************************************************
  5751. NS_IMETHODIMP
  5752. nsDocShell::ScrollByLines(int32_t aNumLines)
  5753. {
  5754. nsIScrollableFrame* sf = GetRootScrollFrame();
  5755. NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE);
  5756. sf->ScrollBy(nsIntPoint(0, aNumLines), nsIScrollableFrame::LINES,
  5757. nsIScrollableFrame::SMOOTH);
  5758. return NS_OK;
  5759. }
  5760. NS_IMETHODIMP
  5761. nsDocShell::ScrollByPages(int32_t aNumPages)
  5762. {
  5763. nsIScrollableFrame* sf = GetRootScrollFrame();
  5764. NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE);
  5765. sf->ScrollBy(nsIntPoint(0, aNumPages), nsIScrollableFrame::PAGES,
  5766. nsIScrollableFrame::SMOOTH);
  5767. return NS_OK;
  5768. }
  5769. //*****************************************************************************
  5770. // nsDocShell::nsIRefreshURI
  5771. //*****************************************************************************
  5772. NS_IMETHODIMP
  5773. nsDocShell::RefreshURI(nsIURI* aURI,
  5774. int32_t aDelay, bool aRepeat,
  5775. bool aMetaRefresh,
  5776. nsIPrincipal* aPrincipal)
  5777. {
  5778. NS_ENSURE_ARG(aURI);
  5779. /* Check if Meta refresh/redirects are permitted. Some
  5780. * embedded applications may not want to do this.
  5781. * Must do this before sending out NOTIFY_REFRESH events
  5782. * because listeners may have side effects (e.g. displaying a
  5783. * button to manually trigger the refresh later).
  5784. */
  5785. bool allowRedirects = true;
  5786. GetAllowMetaRedirects(&allowRedirects);
  5787. if (!allowRedirects) {
  5788. return NS_OK;
  5789. }
  5790. // If any web progress listeners are listening for NOTIFY_REFRESH events,
  5791. // give them a chance to block this refresh.
  5792. bool sameURI;
  5793. nsresult rv = aURI->Equals(mCurrentURI, &sameURI);
  5794. if (NS_FAILED(rv)) {
  5795. sameURI = false;
  5796. }
  5797. if (!RefreshAttempted(this, aURI, aDelay, sameURI)) {
  5798. return NS_OK;
  5799. }
  5800. nsRefreshTimer* refreshTimer = new nsRefreshTimer();
  5801. uint32_t busyFlags = 0;
  5802. GetBusyFlags(&busyFlags);
  5803. nsCOMPtr<nsISupports> dataRef = refreshTimer; // Get the ref count to 1
  5804. refreshTimer->mDocShell = this;
  5805. refreshTimer->mPrincipal = aPrincipal;
  5806. refreshTimer->mURI = aURI;
  5807. refreshTimer->mDelay = aDelay;
  5808. refreshTimer->mRepeat = aRepeat;
  5809. refreshTimer->mMetaRefresh = aMetaRefresh;
  5810. if (!mRefreshURIList) {
  5811. mRefreshURIList = nsArray::Create();
  5812. }
  5813. if (busyFlags & BUSY_FLAGS_BUSY || (!mIsActive && mDisableMetaRefreshWhenInactive)) {
  5814. // We don't want to create the timer right now. Instead queue up the request
  5815. // and trigger the timer in EndPageLoad() or whenever we become active.
  5816. mRefreshURIList->AppendElement(refreshTimer, /*weak =*/ false);
  5817. } else {
  5818. // There is no page loading going on right now. Create the
  5819. // timer and fire it right away.
  5820. nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
  5821. NS_ENSURE_TRUE(timer, NS_ERROR_FAILURE);
  5822. mRefreshURIList->AppendElement(timer, /*weak =*/ false); // owning timer ref
  5823. timer->InitWithCallback(refreshTimer, aDelay, nsITimer::TYPE_ONE_SHOT);
  5824. }
  5825. return NS_OK;
  5826. }
  5827. nsresult
  5828. nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
  5829. int32_t aDelay,
  5830. bool aMetaRefresh,
  5831. nsITimer* aTimer,
  5832. nsIPrincipal* aPrincipal)
  5833. {
  5834. NS_PRECONDITION(aTimer, "Must have a timer here");
  5835. // Remove aTimer from mRefreshURIList if needed
  5836. if (mRefreshURIList) {
  5837. uint32_t n = 0;
  5838. mRefreshURIList->GetLength(&n);
  5839. for (uint32_t i = 0; i < n; ++i) {
  5840. nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
  5841. if (timer == aTimer) {
  5842. mRefreshURIList->RemoveElementAt(i);
  5843. break;
  5844. }
  5845. }
  5846. }
  5847. return ForceRefreshURI(aURI, aDelay, aMetaRefresh, aPrincipal);
  5848. }
  5849. NS_IMETHODIMP
  5850. nsDocShell::ForceRefreshURI(nsIURI* aURI, int32_t aDelay, bool aMetaRefresh, nsIPrincipal* aPrincipal)
  5851. {
  5852. NS_ENSURE_ARG(aURI);
  5853. nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
  5854. CreateLoadInfo(getter_AddRefs(loadInfo));
  5855. NS_ENSURE_TRUE(loadInfo, NS_ERROR_OUT_OF_MEMORY);
  5856. /* We do need to pass in a referrer, but we don't want it to
  5857. * be sent to the server.
  5858. */
  5859. loadInfo->SetSendReferrer(false);
  5860. /* for most refreshes the current URI is an appropriate
  5861. * internal referrer
  5862. */
  5863. loadInfo->SetReferrer(mCurrentURI);
  5864. // Set the triggering pricipal to aPrincipal if available, or current
  5865. // document's principal otherwise.
  5866. nsCOMPtr<nsIPrincipal> principal = aPrincipal;
  5867. if (!principal) {
  5868. nsCOMPtr<nsIDocument> doc = GetDocument();
  5869. if (!doc) {
  5870. return NS_ERROR_FAILURE;
  5871. }
  5872. principal = doc->NodePrincipal();
  5873. }
  5874. loadInfo->SetTriggeringPrincipal(principal);
  5875. loadInfo->SetPrincipalIsExplicit(true);
  5876. /* Check if this META refresh causes a redirection
  5877. * to another site.
  5878. */
  5879. bool equalUri = false;
  5880. nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
  5881. if (NS_SUCCEEDED(rv) && (!equalUri) && aMetaRefresh &&
  5882. aDelay <= REFRESH_REDIRECT_TIMER) {
  5883. /* It is a META refresh based redirection within the threshold time
  5884. * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
  5885. * Pass a REPLACE flag to LoadURI().
  5886. */
  5887. loadInfo->SetLoadType(nsIDocShellLoadInfo::loadNormalReplace);
  5888. /* for redirects we mimic HTTP, which passes the
  5889. * original referrer
  5890. */
  5891. nsCOMPtr<nsIURI> internalReferrer;
  5892. GetReferringURI(getter_AddRefs(internalReferrer));
  5893. if (internalReferrer) {
  5894. loadInfo->SetReferrer(internalReferrer);
  5895. }
  5896. } else {
  5897. loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
  5898. }
  5899. /*
  5900. * LoadURI(...) will cancel all refresh timers... This causes the
  5901. * Timer and its refreshData instance to be released...
  5902. */
  5903. LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL, true);
  5904. return NS_OK;
  5905. }
  5906. nsresult
  5907. nsDocShell::SetupRefreshURIFromHeader(nsIURI* aBaseURI,
  5908. nsIPrincipal* aPrincipal,
  5909. const nsACString& aHeader)
  5910. {
  5911. // Refresh headers are parsed with the following format in mind
  5912. // <META HTTP-EQUIV=REFRESH CONTENT="5; URL=http://uri">
  5913. // By the time we are here, the following is true:
  5914. // header = "REFRESH"
  5915. // content = "5; URL=http://uri" // note the URL attribute is
  5916. // optional, if it is absent, the currently loaded url is used.
  5917. // Also note that the seconds and URL separator can be either
  5918. // a ';' or a ','. The ',' separator should be illegal but CNN
  5919. // is using it.
  5920. //
  5921. // We need to handle the following strings, where
  5922. // - X is a set of digits
  5923. // - URI is either a relative or absolute URI
  5924. //
  5925. // Note that URI should start with "url=" but we allow omission
  5926. //
  5927. // "" || ";" || ","
  5928. // empty string. use the currently loaded URI
  5929. // and refresh immediately.
  5930. // "X" || "X;" || "X,"
  5931. // Refresh the currently loaded URI in X seconds.
  5932. // "X; URI" || "X, URI"
  5933. // Refresh using URI as the destination in X seconds.
  5934. // "URI" || "; URI" || ", URI"
  5935. // Refresh immediately using URI as the destination.
  5936. //
  5937. // Currently, anything immediately following the URI, if
  5938. // separated by any char in the set "'\"\t\r\n " will be
  5939. // ignored. So "10; url=go.html ; foo=bar" will work,
  5940. // and so will "10; url='go.html'; foo=bar". However,
  5941. // "10; url=go.html; foo=bar" will result in the uri
  5942. // "go.html;" since ';' and ',' are valid uri characters.
  5943. //
  5944. // Note that we need to remove any tokens wrapping the URI.
  5945. // These tokens currently include spaces, double and single
  5946. // quotes.
  5947. // when done, seconds is 0 or the given number of seconds
  5948. // uriAttrib is empty or the URI specified
  5949. MOZ_ASSERT(aPrincipal);
  5950. nsAutoCString uriAttrib;
  5951. int32_t seconds = 0;
  5952. bool specifiesSeconds = false;
  5953. nsACString::const_iterator iter, tokenStart, doneIterating;
  5954. aHeader.BeginReading(iter);
  5955. aHeader.EndReading(doneIterating);
  5956. // skip leading whitespace
  5957. while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter)) {
  5958. ++iter;
  5959. }
  5960. tokenStart = iter;
  5961. // skip leading + and -
  5962. if (iter != doneIterating && (*iter == '-' || *iter == '+')) {
  5963. ++iter;
  5964. }
  5965. // parse number
  5966. while (iter != doneIterating && (*iter >= '0' && *iter <= '9')) {
  5967. seconds = seconds * 10 + (*iter - '0');
  5968. specifiesSeconds = true;
  5969. ++iter;
  5970. }
  5971. if (iter != doneIterating) {
  5972. // if we started with a '-', number is negative
  5973. if (*tokenStart == '-') {
  5974. seconds = -seconds;
  5975. }
  5976. // skip to next ';' or ','
  5977. nsACString::const_iterator iterAfterDigit = iter;
  5978. while (iter != doneIterating && !(*iter == ';' || *iter == ',')) {
  5979. if (specifiesSeconds) {
  5980. // Non-whitespace characters here mean that the string is
  5981. // malformed but tolerate sites that specify a decimal point,
  5982. // even though meta refresh only works on whole seconds.
  5983. if (iter == iterAfterDigit &&
  5984. !nsCRT::IsAsciiSpace(*iter) && *iter != '.') {
  5985. // The characters between the seconds and the next
  5986. // section are just garbage!
  5987. // e.g. content="2a0z+,URL=http://www.mozilla.org/"
  5988. // Just ignore this redirect.
  5989. return NS_ERROR_FAILURE;
  5990. } else if (nsCRT::IsAsciiSpace(*iter)) {
  5991. // We've had at least one whitespace so tolerate the mistake
  5992. // and drop through.
  5993. // e.g. content="10 foo"
  5994. ++iter;
  5995. break;
  5996. }
  5997. }
  5998. ++iter;
  5999. }
  6000. // skip any remaining whitespace
  6001. while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter)) {
  6002. ++iter;
  6003. }
  6004. // skip ';' or ','
  6005. if (iter != doneIterating && (*iter == ';' || *iter == ',')) {
  6006. ++iter;
  6007. }
  6008. // skip whitespace
  6009. while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter)) {
  6010. ++iter;
  6011. }
  6012. }
  6013. // possible start of URI
  6014. tokenStart = iter;
  6015. // skip "url = " to real start of URI
  6016. if (iter != doneIterating && (*iter == 'u' || *iter == 'U')) {
  6017. ++iter;
  6018. if (iter != doneIterating && (*iter == 'r' || *iter == 'R')) {
  6019. ++iter;
  6020. if (iter != doneIterating && (*iter == 'l' || *iter == 'L')) {
  6021. ++iter;
  6022. // skip whitespace
  6023. while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter)) {
  6024. ++iter;
  6025. }
  6026. if (iter != doneIterating && *iter == '=') {
  6027. ++iter;
  6028. // skip whitespace
  6029. while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter)) {
  6030. ++iter;
  6031. }
  6032. // found real start of URI
  6033. tokenStart = iter;
  6034. }
  6035. }
  6036. }
  6037. }
  6038. // skip a leading '"' or '\''.
  6039. bool isQuotedURI = false;
  6040. if (tokenStart != doneIterating &&
  6041. (*tokenStart == '"' || *tokenStart == '\'')) {
  6042. isQuotedURI = true;
  6043. ++tokenStart;
  6044. }
  6045. // set iter to start of URI
  6046. iter = tokenStart;
  6047. // tokenStart here points to the beginning of URI
  6048. // grab the rest of the URI
  6049. while (iter != doneIterating) {
  6050. if (isQuotedURI && (*iter == '"' || *iter == '\'')) {
  6051. break;
  6052. }
  6053. ++iter;
  6054. }
  6055. // move iter one back if the last character is a '"' or '\''
  6056. if (iter != tokenStart && isQuotedURI) {
  6057. --iter;
  6058. if (!(*iter == '"' || *iter == '\'')) {
  6059. ++iter;
  6060. }
  6061. }
  6062. // URI is whatever's contained from tokenStart to iter.
  6063. // note: if tokenStart == doneIterating, so is iter.
  6064. nsresult rv = NS_OK;
  6065. nsCOMPtr<nsIURI> uri;
  6066. bool specifiesURI = false;
  6067. if (tokenStart == iter) {
  6068. uri = aBaseURI;
  6069. } else {
  6070. uriAttrib = Substring(tokenStart, iter);
  6071. // NS_NewURI takes care of any whitespace surrounding the URL
  6072. rv = NS_NewURI(getter_AddRefs(uri), uriAttrib, nullptr, aBaseURI);
  6073. specifiesURI = true;
  6074. }
  6075. // No URI or seconds were specified
  6076. if (!specifiesSeconds && !specifiesURI) {
  6077. // Do nothing because the alternative is to spin around in a refresh
  6078. // loop forever!
  6079. return NS_ERROR_FAILURE;
  6080. }
  6081. if (NS_SUCCEEDED(rv)) {
  6082. nsCOMPtr<nsIScriptSecurityManager> securityManager(
  6083. do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
  6084. if (NS_SUCCEEDED(rv)) {
  6085. rv = securityManager->CheckLoadURIWithPrincipal(
  6086. aPrincipal, uri,
  6087. nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT);
  6088. if (NS_SUCCEEDED(rv)) {
  6089. bool isjs = true;
  6090. rv = NS_URIChainHasFlags(
  6091. uri, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs);
  6092. NS_ENSURE_SUCCESS(rv, rv);
  6093. if (isjs) {
  6094. return NS_ERROR_FAILURE;
  6095. }
  6096. }
  6097. if (NS_SUCCEEDED(rv)) {
  6098. // Since we can't travel back in time yet, just pretend
  6099. // negative numbers do nothing at all.
  6100. if (seconds < 0) {
  6101. return NS_ERROR_FAILURE;
  6102. }
  6103. rv = RefreshURI(uri, seconds * 1000, false, true, aPrincipal);
  6104. }
  6105. }
  6106. }
  6107. return rv;
  6108. }
  6109. NS_IMETHODIMP
  6110. nsDocShell::SetupRefreshURI(nsIChannel* aChannel)
  6111. {
  6112. nsresult rv;
  6113. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel, &rv));
  6114. if (NS_SUCCEEDED(rv)) {
  6115. nsAutoCString refreshHeader;
  6116. rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("refresh"),
  6117. refreshHeader);
  6118. if (!refreshHeader.IsEmpty()) {
  6119. nsCOMPtr<nsIScriptSecurityManager> secMan =
  6120. do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
  6121. NS_ENSURE_SUCCESS(rv, rv);
  6122. nsCOMPtr<nsIPrincipal> principal;
  6123. rv = secMan->GetChannelResultPrincipal(aChannel,
  6124. getter_AddRefs(principal));
  6125. NS_ENSURE_SUCCESS(rv, rv);
  6126. SetupReferrerFromChannel(aChannel);
  6127. rv = SetupRefreshURIFromHeader(mCurrentURI, principal, refreshHeader);
  6128. if (NS_SUCCEEDED(rv)) {
  6129. return NS_REFRESHURI_HEADER_FOUND;
  6130. }
  6131. }
  6132. }
  6133. return rv;
  6134. }
  6135. static void
  6136. DoCancelRefreshURITimers(nsIMutableArray* aTimerList)
  6137. {
  6138. if (!aTimerList) {
  6139. return;
  6140. }
  6141. uint32_t n = 0;
  6142. aTimerList->GetLength(&n);
  6143. while (n) {
  6144. nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n));
  6145. aTimerList->RemoveElementAt(n); // bye bye owning timer ref
  6146. if (timer) {
  6147. timer->Cancel();
  6148. }
  6149. }
  6150. }
  6151. NS_IMETHODIMP
  6152. nsDocShell::CancelRefreshURITimers()
  6153. {
  6154. DoCancelRefreshURITimers(mRefreshURIList);
  6155. DoCancelRefreshURITimers(mSavedRefreshURIList);
  6156. mRefreshURIList = nullptr;
  6157. mSavedRefreshURIList = nullptr;
  6158. return NS_OK;
  6159. }
  6160. NS_IMETHODIMP
  6161. nsDocShell::GetRefreshPending(bool* aResult)
  6162. {
  6163. if (!mRefreshURIList) {
  6164. *aResult = false;
  6165. return NS_OK;
  6166. }
  6167. uint32_t count;
  6168. nsresult rv = mRefreshURIList->GetLength(&count);
  6169. if (NS_SUCCEEDED(rv)) {
  6170. *aResult = (count != 0);
  6171. }
  6172. return rv;
  6173. }
  6174. NS_IMETHODIMP
  6175. nsDocShell::SuspendRefreshURIs()
  6176. {
  6177. if (mRefreshURIList) {
  6178. uint32_t n = 0;
  6179. mRefreshURIList->GetLength(&n);
  6180. for (uint32_t i = 0; i < n; ++i) {
  6181. nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
  6182. if (!timer) {
  6183. continue; // this must be a nsRefreshURI already
  6184. }
  6185. // Replace this timer object with a nsRefreshTimer object.
  6186. nsCOMPtr<nsITimerCallback> callback;
  6187. timer->GetCallback(getter_AddRefs(callback));
  6188. timer->Cancel();
  6189. nsCOMPtr<nsITimerCallback> rt = do_QueryInterface(callback);
  6190. NS_ASSERTION(rt,
  6191. "RefreshURIList timer callbacks should only be RefreshTimer objects");
  6192. mRefreshURIList->ReplaceElementAt(rt, i, /*weak =*/ false);
  6193. }
  6194. }
  6195. // Suspend refresh URIs for our child shells as well.
  6196. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  6197. while (iter.HasMore()) {
  6198. nsCOMPtr<nsIDocShell> shell = do_QueryObject(iter.GetNext());
  6199. if (shell) {
  6200. shell->SuspendRefreshURIs();
  6201. }
  6202. }
  6203. return NS_OK;
  6204. }
  6205. NS_IMETHODIMP
  6206. nsDocShell::ResumeRefreshURIs()
  6207. {
  6208. RefreshURIFromQueue();
  6209. // Resume refresh URIs for our child shells as well.
  6210. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  6211. while (iter.HasMore()) {
  6212. nsCOMPtr<nsIDocShell> shell = do_QueryObject(iter.GetNext());
  6213. if (shell) {
  6214. shell->ResumeRefreshURIs();
  6215. }
  6216. }
  6217. return NS_OK;
  6218. }
  6219. nsresult
  6220. nsDocShell::RefreshURIFromQueue()
  6221. {
  6222. if (!mRefreshURIList) {
  6223. return NS_OK;
  6224. }
  6225. uint32_t n = 0;
  6226. mRefreshURIList->GetLength(&n);
  6227. while (n) {
  6228. nsCOMPtr<nsITimerCallback> refreshInfo =
  6229. do_QueryElementAt(mRefreshURIList, --n);
  6230. if (refreshInfo) {
  6231. // This is the nsRefreshTimer object, waiting to be
  6232. // setup in a timer object and fired.
  6233. // Create the timer and trigger it.
  6234. uint32_t delay =
  6235. static_cast<nsRefreshTimer*>(
  6236. static_cast<nsITimerCallback*>(refreshInfo))->GetDelay();
  6237. nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
  6238. if (timer) {
  6239. // Replace the nsRefreshTimer element in the queue with
  6240. // its corresponding timer object, so that in case another
  6241. // load comes through before the timer can go off, the timer will
  6242. // get cancelled in CancelRefreshURITimer()
  6243. mRefreshURIList->ReplaceElementAt(timer, n, /*weak =*/ false);
  6244. timer->InitWithCallback(refreshInfo, delay, nsITimer::TYPE_ONE_SHOT);
  6245. }
  6246. }
  6247. }
  6248. return NS_OK;
  6249. }
  6250. //*****************************************************************************
  6251. // nsDocShell::nsIContentViewerContainer
  6252. //*****************************************************************************
  6253. NS_IMETHODIMP
  6254. nsDocShell::Embed(nsIContentViewer* aContentViewer,
  6255. const char* aCommand, nsISupports* aExtraInfo)
  6256. {
  6257. // Save the LayoutHistoryState of the previous document, before
  6258. // setting up new document
  6259. PersistLayoutHistoryState();
  6260. nsresult rv = SetupNewViewer(aContentViewer);
  6261. NS_ENSURE_SUCCESS(rv, rv);
  6262. // If we are loading a wyciwyg url from history, change the base URI for
  6263. // the document to the original http url that created the document.write().
  6264. // This makes sure that all relative urls in a document.written page loaded
  6265. // via history work properly.
  6266. if (mCurrentURI &&
  6267. (mLoadType & LOAD_CMD_HISTORY ||
  6268. mLoadType == LOAD_RELOAD_NORMAL ||
  6269. mLoadType == LOAD_RELOAD_CHARSET_CHANGE)) {
  6270. bool isWyciwyg = false;
  6271. // Check if the url is wyciwyg
  6272. rv = mCurrentURI->SchemeIs("wyciwyg", &isWyciwyg);
  6273. if (isWyciwyg && NS_SUCCEEDED(rv)) {
  6274. SetBaseUrlForWyciwyg(aContentViewer);
  6275. }
  6276. }
  6277. // XXX What if SetupNewViewer fails?
  6278. if (mLSHE) {
  6279. // Restore the editing state, if it's stored in session history.
  6280. if (mLSHE->HasDetachedEditor()) {
  6281. ReattachEditorToWindow(mLSHE);
  6282. }
  6283. // Set history.state
  6284. SetDocCurrentStateObj(mLSHE);
  6285. SetHistoryEntry(&mOSHE, mLSHE);
  6286. }
  6287. bool updateHistory = true;
  6288. // Determine if this type of load should update history
  6289. switch (mLoadType) {
  6290. case LOAD_NORMAL_REPLACE:
  6291. case LOAD_STOP_CONTENT_AND_REPLACE:
  6292. case LOAD_RELOAD_BYPASS_CACHE:
  6293. case LOAD_RELOAD_BYPASS_PROXY:
  6294. case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
  6295. case LOAD_REPLACE_BYPASS_CACHE:
  6296. updateHistory = false;
  6297. break;
  6298. default:
  6299. break;
  6300. }
  6301. if (!updateHistory) {
  6302. SetLayoutHistoryState(nullptr);
  6303. }
  6304. return NS_OK;
  6305. }
  6306. NS_IMETHODIMP
  6307. nsDocShell::SetIsPrinting(bool aIsPrinting)
  6308. {
  6309. mIsPrintingOrPP = aIsPrinting;
  6310. return NS_OK;
  6311. }
  6312. //*****************************************************************************
  6313. // nsDocShell::nsIWebProgressListener
  6314. //*****************************************************************************
  6315. NS_IMETHODIMP
  6316. nsDocShell::OnProgressChange(nsIWebProgress* aProgress,
  6317. nsIRequest* aRequest,
  6318. int32_t aCurSelfProgress,
  6319. int32_t aMaxSelfProgress,
  6320. int32_t aCurTotalProgress,
  6321. int32_t aMaxTotalProgress)
  6322. {
  6323. return NS_OK;
  6324. }
  6325. NS_IMETHODIMP
  6326. nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
  6327. uint32_t aStateFlags, nsresult aStatus)
  6328. {
  6329. if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) {
  6330. // Save timing statistics.
  6331. nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
  6332. nsCOMPtr<nsIURI> uri;
  6333. channel->GetURI(getter_AddRefs(uri));
  6334. nsAutoCString aURI;
  6335. uri->GetAsciiSpec(aURI);
  6336. nsCOMPtr<nsIWyciwygChannel> wcwgChannel(do_QueryInterface(aRequest));
  6337. nsCOMPtr<nsIWebProgress> webProgress =
  6338. do_QueryInterface(GetAsSupports(this));
  6339. // We don't update navigation timing for wyciwyg channels
  6340. if (this == aProgress && !wcwgChannel) {
  6341. MaybeInitTiming();
  6342. mTiming->NotifyFetchStart(uri,
  6343. ConvertLoadTypeToNavigationType(mLoadType));
  6344. }
  6345. // Was the wyciwyg document loaded on this docshell?
  6346. if (wcwgChannel && !mLSHE && (mItemType == typeContent) &&
  6347. aProgress == webProgress.get()) {
  6348. bool equalUri = true;
  6349. // Store the wyciwyg url in session history, only if it is
  6350. // being loaded fresh for the first time. We don't want
  6351. // multiple entries for successive loads
  6352. if (mCurrentURI &&
  6353. NS_SUCCEEDED(uri->Equals(mCurrentURI, &equalUri)) &&
  6354. !equalUri) {
  6355. nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
  6356. GetSameTypeParent(getter_AddRefs(parentAsItem));
  6357. nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
  6358. bool inOnLoadHandler = false;
  6359. if (parentDS) {
  6360. parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
  6361. }
  6362. if (inOnLoadHandler) {
  6363. // We're handling parent's load event listener, which causes
  6364. // document.write in a subdocument.
  6365. // Need to clear the session history for all child
  6366. // docshells so that we can handle them like they would
  6367. // all be added dynamically.
  6368. nsCOMPtr<nsIDocShell> parent = do_QueryInterface(parentAsItem);
  6369. if (parent) {
  6370. bool oshe = false;
  6371. nsCOMPtr<nsISHEntry> entry;
  6372. parent->GetCurrentSHEntry(getter_AddRefs(entry), &oshe);
  6373. static_cast<nsDocShell*>(parent.get())->ClearFrameHistory(entry);
  6374. }
  6375. }
  6376. // This is a document.write(). Get the made-up url
  6377. // from the channel and store it in session history.
  6378. // Pass false for aCloneChildren, since we're creating
  6379. // a new DOM here.
  6380. AddToSessionHistory(uri, wcwgChannel, nullptr, nullptr, false,
  6381. getter_AddRefs(mLSHE));
  6382. SetCurrentURI(uri, aRequest, true, 0);
  6383. // Save history state of the previous page
  6384. PersistLayoutHistoryState();
  6385. // We'll never get an Embed() for this load, so just go ahead
  6386. // and SetHistoryEntry now.
  6387. SetHistoryEntry(&mOSHE, mLSHE);
  6388. }
  6389. }
  6390. // Page has begun to load
  6391. mBusyFlags = BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD;
  6392. if ((aStateFlags & STATE_RESTORING) == 0) {
  6393. // Show the progress cursor if the pref is set
  6394. if (nsContentUtils::UseActivityCursor()) {
  6395. nsCOMPtr<nsIWidget> mainWidget;
  6396. GetMainWidget(getter_AddRefs(mainWidget));
  6397. if (mainWidget) {
  6398. mainWidget->SetCursor(eCursor_spinning);
  6399. }
  6400. }
  6401. }
  6402. } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) {
  6403. // Page is loading
  6404. mBusyFlags = BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING;
  6405. } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) {
  6406. // Page has finished loading
  6407. mBusyFlags = BUSY_FLAGS_NONE;
  6408. // Hide the progress cursor if the pref is set
  6409. if (nsContentUtils::UseActivityCursor()) {
  6410. nsCOMPtr<nsIWidget> mainWidget;
  6411. GetMainWidget(getter_AddRefs(mainWidget));
  6412. if (mainWidget) {
  6413. mainWidget->SetCursor(eCursor_standard);
  6414. }
  6415. }
  6416. }
  6417. if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) {
  6418. nsCOMPtr<nsIWebProgress> webProgress =
  6419. do_QueryInterface(GetAsSupports(this));
  6420. // Is the document stop notification for this document?
  6421. if (aProgress == webProgress.get()) {
  6422. nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
  6423. EndPageLoad(aProgress, channel, aStatus);
  6424. }
  6425. }
  6426. // note that redirect state changes will go through here as well, but it
  6427. // is better to handle those in OnRedirectStateChange where more
  6428. // information is available.
  6429. return NS_OK;
  6430. }
  6431. NS_IMETHODIMP
  6432. nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
  6433. nsIURI* aURI, uint32_t aFlags)
  6434. {
  6435. NS_NOTREACHED("notification excluded in AddProgressListener(...)");
  6436. return NS_OK;
  6437. }
  6438. void
  6439. nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
  6440. nsIChannel* aNewChannel,
  6441. uint32_t aRedirectFlags,
  6442. uint32_t aStateFlags)
  6443. {
  6444. NS_ASSERTION(aStateFlags & STATE_REDIRECTING,
  6445. "Calling OnRedirectStateChange when there is no redirect");
  6446. // If mixed content is allowed for the old channel, we forward
  6447. // the permission to the new channel if it has the same origin
  6448. // as the old one.
  6449. if (mMixedContentChannel && mMixedContentChannel == aOldChannel) {
  6450. nsresult rv = nsContentUtils::CheckSameOrigin(mMixedContentChannel, aNewChannel);
  6451. if (NS_SUCCEEDED(rv)) {
  6452. SetMixedContentChannel(aNewChannel); // Same origin: forward permission.
  6453. } else {
  6454. SetMixedContentChannel(nullptr); // Different origin: clear mMixedContentChannel.
  6455. }
  6456. }
  6457. if (!(aStateFlags & STATE_IS_DOCUMENT)) {
  6458. return; // not a toplevel document
  6459. }
  6460. nsCOMPtr<nsIURI> oldURI, newURI;
  6461. aOldChannel->GetURI(getter_AddRefs(oldURI));
  6462. aNewChannel->GetURI(getter_AddRefs(newURI));
  6463. if (!oldURI || !newURI) {
  6464. return;
  6465. }
  6466. // Below a URI visit is saved (see AddURIVisit method doc).
  6467. // The visit chain looks something like:
  6468. // ...
  6469. // Site N - 1
  6470. // => Site N
  6471. // (redirect to =>) Site N + 1 (we are here!)
  6472. // Get N - 1 and transition type
  6473. nsCOMPtr<nsIURI> previousURI;
  6474. uint32_t previousFlags = 0;
  6475. ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags);
  6476. if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL ||
  6477. ChannelIsPost(aOldChannel)) {
  6478. // 1. Internal redirects are ignored because they are specific to the
  6479. // channel implementation.
  6480. // 2. POSTs are not saved by global history.
  6481. //
  6482. // Regardless, we need to propagate the previous visit to the new
  6483. // channel.
  6484. SaveLastVisit(aNewChannel, previousURI, previousFlags);
  6485. } else {
  6486. nsCOMPtr<nsIURI> referrer;
  6487. // Treat referrer as null if there is an error getting it.
  6488. (void)NS_GetReferrerFromChannel(aOldChannel, getter_AddRefs(referrer));
  6489. // Get the HTTP response code, if available.
  6490. uint32_t responseStatus = 0;
  6491. nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel);
  6492. if (httpChannel) {
  6493. (void)httpChannel->GetResponseStatus(&responseStatus);
  6494. }
  6495. // Add visit N -1 => N
  6496. AddURIVisit(oldURI, referrer, previousURI, previousFlags, responseStatus);
  6497. // Since N + 1 could be the final destination, we will not save N => N + 1
  6498. // here. OnNewURI will do that, so we will cache it.
  6499. SaveLastVisit(aNewChannel, oldURI, aRedirectFlags);
  6500. }
  6501. // check if the new load should go through the application cache.
  6502. nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
  6503. do_QueryInterface(aNewChannel);
  6504. if (appCacheChannel) {
  6505. if (GeckoProcessType_Default != XRE_GetProcessType()) {
  6506. // Permission will be checked in the parent process.
  6507. appCacheChannel->SetChooseApplicationCache(true);
  6508. } else {
  6509. nsCOMPtr<nsIScriptSecurityManager> secMan =
  6510. do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
  6511. if (secMan) {
  6512. nsCOMPtr<nsIPrincipal> principal;
  6513. secMan->GetDocShellCodebasePrincipal(newURI, this,
  6514. getter_AddRefs(principal));
  6515. appCacheChannel->SetChooseApplicationCache(
  6516. NS_ShouldCheckAppCache(principal, UsePrivateBrowsing()));
  6517. }
  6518. }
  6519. }
  6520. if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
  6521. mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
  6522. mLoadType = LOAD_NORMAL_REPLACE;
  6523. SetHistoryEntry(&mLSHE, nullptr);
  6524. }
  6525. }
  6526. NS_IMETHODIMP
  6527. nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress,
  6528. nsIRequest* aRequest,
  6529. nsresult aStatus, const char16_t* aMessage)
  6530. {
  6531. NS_NOTREACHED("notification excluded in AddProgressListener(...)");
  6532. return NS_OK;
  6533. }
  6534. NS_IMETHODIMP
  6535. nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress,
  6536. nsIRequest* aRequest, uint32_t aState)
  6537. {
  6538. NS_NOTREACHED("notification excluded in AddProgressListener(...)");
  6539. return NS_OK;
  6540. }
  6541. nsresult
  6542. nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
  6543. nsIChannel* aChannel, nsresult aStatus)
  6544. {
  6545. if (!aChannel) {
  6546. return NS_ERROR_NULL_POINTER;
  6547. }
  6548. nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
  6549. if (reporter) {
  6550. reporter->FlushConsoleReports(GetDocument());
  6551. }
  6552. nsCOMPtr<nsIURI> url;
  6553. nsresult rv = aChannel->GetURI(getter_AddRefs(url));
  6554. if (NS_FAILED(rv)) {
  6555. return rv;
  6556. }
  6557. nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel);
  6558. if (timingChannel) {
  6559. TimeStamp channelCreationTime;
  6560. rv = timingChannel->GetChannelCreation(&channelCreationTime);
  6561. if (NS_SUCCEEDED(rv) && !channelCreationTime.IsNull()) {
  6562. nsCOMPtr<nsPILoadGroupInternal> internalLoadGroup =
  6563. do_QueryInterface(mLoadGroup);
  6564. if (internalLoadGroup) {
  6565. internalLoadGroup->OnEndPageLoad(aChannel);
  6566. }
  6567. }
  6568. }
  6569. // Timing is picked up by the window, we don't need it anymore
  6570. mTiming = nullptr;
  6571. // clean up reload state for meta charset
  6572. if (eCharsetReloadRequested == mCharsetReloadState) {
  6573. mCharsetReloadState = eCharsetReloadStopOrigional;
  6574. } else {
  6575. mCharsetReloadState = eCharsetReloadInit;
  6576. }
  6577. // Save a pointer to the currently-loading history entry.
  6578. // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history
  6579. // entry further down in this method.
  6580. nsCOMPtr<nsISHEntry> loadingSHE = mLSHE;
  6581. mozilla::Unused << loadingSHE; // XXX: Not sure if we need this anymore
  6582. //
  6583. // one of many safeguards that prevent death and destruction if
  6584. // someone is so very very rude as to bring this window down
  6585. // during this load handler.
  6586. //
  6587. nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
  6588. // Notify the ContentViewer that the Document has finished loading. This
  6589. // will cause any OnLoad(...) and PopState(...) handlers to fire.
  6590. if (!mEODForCurrentDocument && mContentViewer) {
  6591. mIsExecutingOnLoadHandler = true;
  6592. mContentViewer->LoadComplete(aStatus);
  6593. mIsExecutingOnLoadHandler = false;
  6594. mEODForCurrentDocument = true;
  6595. // If all documents have completed their loading
  6596. // favor native event dispatch priorities
  6597. // over performance
  6598. if (--gNumberOfDocumentsLoading == 0) {
  6599. // Hint to use normal native event dispatch priorities
  6600. FavorPerformanceHint(false);
  6601. }
  6602. }
  6603. /* Check if the httpChannel has any cache-control related response headers,
  6604. * like no-store, no-cache. If so, update SHEntry so that
  6605. * when a user goes back/forward to this page, we appropriately do
  6606. * form value restoration or load from server.
  6607. */
  6608. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
  6609. if (!httpChannel) {
  6610. // HttpChannel could be hiding underneath a Multipart channel.
  6611. GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
  6612. }
  6613. if (httpChannel) {
  6614. // figure out if SH should be saving layout state.
  6615. bool discardLayoutState = ShouldDiscardLayoutState(httpChannel);
  6616. if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) &&
  6617. (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) {
  6618. mLSHE->SetSaveLayoutStateFlag(false);
  6619. }
  6620. }
  6621. // Clear mLSHE after calling the onLoadHandlers. This way, if the
  6622. // onLoadHandler tries to load something different in
  6623. // itself or one of its children, we can deal with it appropriately.
  6624. if (mLSHE) {
  6625. mLSHE->SetLoadType(nsIDocShellLoadInfo::loadHistory);
  6626. // Clear the mLSHE reference to indicate document loading is done one
  6627. // way or another.
  6628. SetHistoryEntry(&mLSHE, nullptr);
  6629. }
  6630. // if there's a refresh header in the channel, this method
  6631. // will set it up for us.
  6632. if (mIsActive || !mDisableMetaRefreshWhenInactive)
  6633. RefreshURIFromQueue();
  6634. // Test whether this is the top frame or a subframe
  6635. bool isTopFrame = true;
  6636. nsCOMPtr<nsIDocShellTreeItem> targetParentTreeItem;
  6637. rv = GetSameTypeParent(getter_AddRefs(targetParentTreeItem));
  6638. if (NS_SUCCEEDED(rv) && targetParentTreeItem) {
  6639. isTopFrame = false;
  6640. }
  6641. //
  6642. // If the page load failed, then deal with the error condition...
  6643. // Errors are handled as follows:
  6644. // 1. Check to see if it's a file not found error or bad content
  6645. // encoding error.
  6646. // 2. Send the URI to a keyword server (if enabled)
  6647. // 3. If the error was DNS failure, then add www and .com to the URI
  6648. // (if appropriate).
  6649. // 4. Throw an error dialog box...
  6650. //
  6651. if (url && NS_FAILED(aStatus)) {
  6652. if (aStatus == NS_ERROR_FILE_NOT_FOUND ||
  6653. aStatus == NS_ERROR_FILE_ACCESS_DENIED ||
  6654. aStatus == NS_ERROR_CORRUPTED_CONTENT ||
  6655. aStatus == NS_ERROR_INVALID_CONTENT_ENCODING) {
  6656. DisplayLoadError(aStatus, url, nullptr, aChannel);
  6657. return NS_OK;
  6658. } else if (aStatus == NS_ERROR_INVALID_SIGNATURE) {
  6659. // NS_ERROR_INVALID_SIGNATURE indicates a content-signature error.
  6660. // This currently only happens in case a remote about page fails.
  6661. // We have to load a fallback in this case.
  6662. // XXX: We always load about blank here, firefox has to overwrite this if
  6663. // it wants to display something else.
  6664. return LoadURI(u"about:blank", // URI string
  6665. nsIChannel::LOAD_NORMAL, // Load flags
  6666. nullptr, // Referring URI
  6667. nullptr, // Post data stream
  6668. nullptr); // Headers stream
  6669. }
  6670. // Handle iframe document not loading error because source was
  6671. // a tracking URL. We make a note of this iframe node by including
  6672. // it in a dedicated array of blocked tracking nodes under its parent
  6673. // document. (document of parent window of blocked document)
  6674. if (isTopFrame == false && aStatus == NS_ERROR_TRACKING_URI) {
  6675. // frameElement is our nsIContent to be annotated
  6676. nsCOMPtr<nsIDOMElement> frameElement;
  6677. nsPIDOMWindowOuter* thisWindow = GetWindow();
  6678. if (!thisWindow) {
  6679. return NS_OK;
  6680. }
  6681. frameElement = thisWindow->GetFrameElement();
  6682. if (!frameElement) {
  6683. return NS_OK;
  6684. }
  6685. // Parent window
  6686. nsCOMPtr<nsIDocShellTreeItem> parentItem;
  6687. GetSameTypeParent(getter_AddRefs(parentItem));
  6688. if (!parentItem) {
  6689. return NS_OK;
  6690. }
  6691. nsCOMPtr<nsIDocument> parentDoc;
  6692. parentDoc = parentItem->GetDocument();
  6693. if (!parentDoc) {
  6694. return NS_OK;
  6695. }
  6696. nsCOMPtr<nsIContent> cont = do_QueryInterface(frameElement);
  6697. parentDoc->AddBlockedTrackingNode(cont);
  6698. return NS_OK;
  6699. }
  6700. if (sURIFixup) {
  6701. //
  6702. // Try and make an alternative URI from the old one
  6703. //
  6704. nsCOMPtr<nsIURI> newURI;
  6705. nsCOMPtr<nsIInputStream> newPostData;
  6706. nsAutoCString oldSpec;
  6707. url->GetSpec(oldSpec);
  6708. //
  6709. // First try keyword fixup
  6710. //
  6711. nsAutoString keywordProviderName, keywordAsSent;
  6712. if (aStatus == NS_ERROR_UNKNOWN_HOST && mAllowKeywordFixup) {
  6713. bool keywordsEnabled = Preferences::GetBool("keyword.enabled", false);
  6714. nsAutoCString host;
  6715. url->GetHost(host);
  6716. nsAutoCString scheme;
  6717. url->GetScheme(scheme);
  6718. int32_t dotLoc = host.FindChar('.');
  6719. // we should only perform a keyword search under the following
  6720. // conditions:
  6721. // (0) Pref keyword.enabled is true
  6722. // (1) the url scheme is http (or https)
  6723. // (2) the url does not have a protocol scheme
  6724. // If we don't enforce such a policy, then we end up doing
  6725. // keyword searchs on urls we don't intend like imap, file,
  6726. // mailbox, etc. This could lead to a security problem where we
  6727. // send data to the keyword server that we shouldn't be.
  6728. // Someone needs to clean up keywords in general so we can
  6729. // determine on a per url basis if we want keywords
  6730. // enabled...this is just a bandaid...
  6731. if (keywordsEnabled && !scheme.IsEmpty() &&
  6732. (scheme.Find("http") != 0)) {
  6733. keywordsEnabled = false;
  6734. }
  6735. if (keywordsEnabled && (kNotFound == dotLoc)) {
  6736. nsCOMPtr<nsIURIFixupInfo> info;
  6737. // only send non-qualified hosts to the keyword server
  6738. if (!mOriginalUriString.IsEmpty()) {
  6739. sURIFixup->KeywordToURI(mOriginalUriString,
  6740. getter_AddRefs(newPostData),
  6741. getter_AddRefs(info));
  6742. } else {
  6743. //
  6744. // If this string was passed through nsStandardURL by
  6745. // chance, then it may have been converted from UTF-8 to
  6746. // ACE, which would result in a completely bogus keyword
  6747. // query. Here we try to recover the original Unicode
  6748. // value, but this is not 100% correct since the value may
  6749. // have been normalized per the IDN normalization rules.
  6750. //
  6751. // Since we don't have access to the exact original string
  6752. // that was entered by the user, this will just have to do.
  6753. bool isACE;
  6754. nsAutoCString utf8Host;
  6755. nsCOMPtr<nsIIDNService> idnSrv =
  6756. do_GetService(NS_IDNSERVICE_CONTRACTID);
  6757. if (idnSrv &&
  6758. NS_SUCCEEDED(idnSrv->IsACE(host, &isACE)) && isACE &&
  6759. NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host))) {
  6760. sURIFixup->KeywordToURI(utf8Host,
  6761. getter_AddRefs(newPostData),
  6762. getter_AddRefs(info));
  6763. } else {
  6764. sURIFixup->KeywordToURI(host,
  6765. getter_AddRefs(newPostData),
  6766. getter_AddRefs(info));
  6767. }
  6768. }
  6769. info->GetPreferredURI(getter_AddRefs(newURI));
  6770. if (newURI) {
  6771. info->GetKeywordAsSent(keywordAsSent);
  6772. info->GetKeywordProviderName(keywordProviderName);
  6773. }
  6774. } // end keywordsEnabled
  6775. }
  6776. //
  6777. // Now try change the address, e.g. turn http://foo into
  6778. // http://www.foo.com
  6779. //
  6780. if (aStatus == NS_ERROR_UNKNOWN_HOST ||
  6781. aStatus == NS_ERROR_NET_RESET) {
  6782. bool doCreateAlternate = true;
  6783. // Skip fixup for anything except a normal document load
  6784. // operation on the topframe.
  6785. if (mLoadType != LOAD_NORMAL || !isTopFrame) {
  6786. doCreateAlternate = false;
  6787. } else {
  6788. // Test if keyword lookup produced a new URI or not
  6789. if (newURI) {
  6790. bool sameURI = false;
  6791. url->Equals(newURI, &sameURI);
  6792. if (!sameURI) {
  6793. // Keyword lookup made a new URI so no need to try
  6794. // an alternate one.
  6795. doCreateAlternate = false;
  6796. }
  6797. }
  6798. if (doCreateAlternate) {
  6799. // Skip doing this if our channel was redirected, because we
  6800. // shouldn't be guessing things about the post-redirect URI.
  6801. nsLoadFlags loadFlags = 0;
  6802. if (NS_FAILED(aChannel->GetLoadFlags(&loadFlags)) ||
  6803. (loadFlags & nsIChannel::LOAD_REPLACE)) {
  6804. doCreateAlternate = false;
  6805. }
  6806. }
  6807. }
  6808. if (doCreateAlternate) {
  6809. newURI = nullptr;
  6810. newPostData = nullptr;
  6811. keywordProviderName.Truncate();
  6812. keywordAsSent.Truncate();
  6813. sURIFixup->CreateFixupURI(oldSpec,
  6814. nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI,
  6815. getter_AddRefs(newPostData),
  6816. getter_AddRefs(newURI));
  6817. }
  6818. }
  6819. // Did we make a new URI that is different to the old one? If so
  6820. // load it.
  6821. //
  6822. if (newURI) {
  6823. // Make sure the new URI is different from the old one,
  6824. // otherwise there's little point trying to load it again.
  6825. bool sameURI = false;
  6826. url->Equals(newURI, &sameURI);
  6827. if (!sameURI) {
  6828. nsAutoCString newSpec;
  6829. newURI->GetSpec(newSpec);
  6830. NS_ConvertUTF8toUTF16 newSpecW(newSpec);
  6831. // This notification is meant for Firefox Health Report so it
  6832. // can increment counts from the search engine
  6833. MaybeNotifyKeywordSearchLoading(keywordProviderName, keywordAsSent);
  6834. return LoadURI(newSpecW.get(), // URI string
  6835. LOAD_FLAGS_NONE, // Load flags
  6836. nullptr, // Referring URI
  6837. newPostData, // Post data stream
  6838. nullptr); // Headers stream
  6839. }
  6840. }
  6841. }
  6842. // Well, fixup didn't work :-(
  6843. // It is time to throw an error dialog box, and be done with it...
  6844. // Errors to be shown only on top-level frames
  6845. if ((aStatus == NS_ERROR_UNKNOWN_HOST ||
  6846. aStatus == NS_ERROR_CONNECTION_REFUSED ||
  6847. aStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
  6848. aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED) &&
  6849. (isTopFrame || UseErrorPages())) {
  6850. DisplayLoadError(aStatus, url, nullptr, aChannel);
  6851. } else if (aStatus == NS_ERROR_NET_TIMEOUT ||
  6852. aStatus == NS_ERROR_REDIRECT_LOOP ||
  6853. aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
  6854. aStatus == NS_ERROR_NET_INTERRUPT ||
  6855. aStatus == NS_ERROR_NET_RESET ||
  6856. aStatus == NS_ERROR_OFFLINE ||
  6857. aStatus == NS_ERROR_MALWARE_URI ||
  6858. aStatus == NS_ERROR_PHISHING_URI ||
  6859. aStatus == NS_ERROR_UNWANTED_URI ||
  6860. aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
  6861. aStatus == NS_ERROR_REMOTE_XUL ||
  6862. aStatus == NS_ERROR_INTERCEPTION_FAILED ||
  6863. aStatus == NS_ERROR_NET_INADEQUATE_SECURITY ||
  6864. NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) {
  6865. // Errors to be shown for any frame
  6866. DisplayLoadError(aStatus, url, nullptr, aChannel);
  6867. } else if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
  6868. // Non-caching channels will simply return NS_ERROR_OFFLINE.
  6869. // Caching channels would have to look at their flags to work
  6870. // out which error to return. Or we can fix up the error here.
  6871. if (!(mLoadType & LOAD_CMD_HISTORY)) {
  6872. aStatus = NS_ERROR_OFFLINE;
  6873. }
  6874. DisplayLoadError(aStatus, url, nullptr, aChannel);
  6875. }
  6876. } else if (url && NS_SUCCEEDED(aStatus)) {
  6877. // If we have a host
  6878. mozilla::net::PredictorLearnRedirect(url, aChannel, this);
  6879. }
  6880. return NS_OK;
  6881. }
  6882. //*****************************************************************************
  6883. // nsDocShell: Content Viewer Management
  6884. //*****************************************************************************
  6885. nsresult
  6886. nsDocShell::EnsureContentViewer()
  6887. {
  6888. if (mContentViewer) {
  6889. return NS_OK;
  6890. }
  6891. if (mIsBeingDestroyed) {
  6892. return NS_ERROR_FAILURE;
  6893. }
  6894. nsCOMPtr<nsIURI> baseURI;
  6895. nsIPrincipal* principal = GetInheritedPrincipal(false);
  6896. nsCOMPtr<nsIDocShellTreeItem> parentItem;
  6897. GetSameTypeParent(getter_AddRefs(parentItem));
  6898. if (parentItem) {
  6899. if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) {
  6900. nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal();
  6901. if (parentElement) {
  6902. baseURI = parentElement->GetBaseURI();
  6903. }
  6904. }
  6905. }
  6906. nsresult rv = CreateAboutBlankContentViewer(principal, baseURI);
  6907. NS_ENSURE_STATE(mContentViewer);
  6908. if (NS_SUCCEEDED(rv)) {
  6909. nsCOMPtr<nsIDocument> doc(GetDocument());
  6910. NS_ASSERTION(doc,
  6911. "Should have doc if CreateAboutBlankContentViewer "
  6912. "succeeded!");
  6913. doc->SetIsInitialDocument(true);
  6914. }
  6915. return rv;
  6916. }
  6917. nsresult
  6918. nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
  6919. nsIURI* aBaseURI,
  6920. bool aTryToSaveOldPresentation)
  6921. {
  6922. nsCOMPtr<nsIDocument> blankDoc;
  6923. nsCOMPtr<nsIContentViewer> viewer;
  6924. nsresult rv = NS_ERROR_FAILURE;
  6925. /* mCreatingDocument should never be true at this point. However, it's
  6926. a theoretical possibility. We want to know about it and make it stop,
  6927. and this sounds like a job for an assertion. */
  6928. NS_ASSERTION(!mCreatingDocument,
  6929. "infinite(?) loop creating document averted");
  6930. if (mCreatingDocument) {
  6931. return NS_ERROR_FAILURE;
  6932. }
  6933. // mContentViewer->PermitUnload may release |this| docshell.
  6934. nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
  6935. AutoRestore<bool> creatingDocument(mCreatingDocument);
  6936. mCreatingDocument = true;
  6937. if (aPrincipal && !nsContentUtils::IsSystemPrincipal(aPrincipal) &&
  6938. mItemType != typeChrome) {
  6939. MOZ_ASSERT(ChromeUtils::IsOriginAttributesEqualIgnoringAddonId(
  6940. BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(),
  6941. mOriginAttributes));
  6942. }
  6943. // Make sure timing is created. But first record whether we had it
  6944. // already, so we don't clobber the timing for an in-progress load.
  6945. bool hadTiming = mTiming;
  6946. MaybeInitTiming();
  6947. if (mContentViewer) {
  6948. // We've got a content viewer already. Make sure the user
  6949. // permits us to discard the current document and replace it
  6950. // with about:blank. And also ensure we fire the unload events
  6951. // in the current document.
  6952. // Unload gets fired first for
  6953. // document loaded from the session history.
  6954. mTiming->NotifyBeforeUnload();
  6955. bool okToUnload;
  6956. rv = mContentViewer->PermitUnload(&okToUnload);
  6957. if (NS_SUCCEEDED(rv) && !okToUnload) {
  6958. // The user chose not to unload the page, interrupt the load.
  6959. return NS_ERROR_FAILURE;
  6960. }
  6961. mSavingOldViewer = aTryToSaveOldPresentation &&
  6962. CanSavePresentation(LOAD_NORMAL, nullptr, nullptr);
  6963. if (mTiming) {
  6964. mTiming->NotifyUnloadAccepted(mCurrentURI);
  6965. }
  6966. // Make sure to blow away our mLoadingURI just in case. No loads
  6967. // from inside this pagehide.
  6968. mLoadingURI = nullptr;
  6969. // Stop any in-progress loading, so that we don't accidentally trigger any
  6970. // PageShow notifications from Embed() interrupting our loading below.
  6971. Stop();
  6972. // Notify the current document that it is about to be unloaded!!
  6973. //
  6974. // It is important to fire the unload() notification *before* any state
  6975. // is changed within the DocShell - otherwise, javascript will get the
  6976. // wrong information :-(
  6977. //
  6978. (void)FirePageHideNotification(!mSavingOldViewer);
  6979. }
  6980. // Now make sure we don't think we're in the middle of firing unload after
  6981. // this point. This will make us fire unload when the about:blank document
  6982. // unloads... but that's ok, more or less. Would be nice if it fired load
  6983. // too, of course.
  6984. mFiredUnloadEvent = false;
  6985. nsCOMPtr<nsIDocumentLoaderFactory> docFactory =
  6986. nsContentUtils::FindInternalContentViewer(NS_LITERAL_CSTRING("text/html"));
  6987. if (docFactory) {
  6988. nsCOMPtr<nsIPrincipal> principal;
  6989. if (mSandboxFlags & SANDBOXED_ORIGIN) {
  6990. if (aPrincipal) {
  6991. principal = nsNullPrincipal::CreateWithInheritedAttributes(aPrincipal);
  6992. } else {
  6993. principal = nsNullPrincipal::CreateWithInheritedAttributes(this);
  6994. }
  6995. } else {
  6996. principal = aPrincipal;
  6997. }
  6998. // generate (about:blank) document to load
  6999. docFactory->CreateBlankDocument(mLoadGroup, principal,
  7000. getter_AddRefs(blankDoc));
  7001. if (blankDoc) {
  7002. // Hack: set the base URI manually, since this document never
  7003. // got Reset() with a channel.
  7004. blankDoc->SetBaseURI(aBaseURI);
  7005. blankDoc->SetContainer(this);
  7006. // Copy our sandbox flags to the document. These are immutable
  7007. // after being set here.
  7008. blankDoc->SetSandboxFlags(mSandboxFlags);
  7009. // create a content viewer for us and the new document
  7010. docFactory->CreateInstanceForDocument(
  7011. NS_ISUPPORTS_CAST(nsIDocShell*, this), blankDoc, "view",
  7012. getter_AddRefs(viewer));
  7013. // hook 'em up
  7014. if (viewer) {
  7015. viewer->SetContainer(this);
  7016. rv = Embed(viewer, "", 0);
  7017. NS_ENSURE_SUCCESS(rv, rv);
  7018. SetCurrentURI(blankDoc->GetDocumentURI(), nullptr, true, 0);
  7019. rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
  7020. }
  7021. }
  7022. }
  7023. // The transient about:blank viewer doesn't have a session history entry.
  7024. SetHistoryEntry(&mOSHE, nullptr);
  7025. // Clear out our mTiming like we would in EndPageLoad, if we didn't
  7026. // have one before entering this function.
  7027. if (!hadTiming) {
  7028. mTiming = nullptr;
  7029. mBlankTiming = true;
  7030. }
  7031. return rv;
  7032. }
  7033. NS_IMETHODIMP
  7034. nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal)
  7035. {
  7036. return CreateAboutBlankContentViewer(aPrincipal, nullptr);
  7037. }
  7038. bool
  7039. nsDocShell::CanSavePresentation(uint32_t aLoadType,
  7040. nsIRequest* aNewRequest,
  7041. nsIDocument* aNewDocument)
  7042. {
  7043. if (!mOSHE) {
  7044. return false; // no entry to save into
  7045. }
  7046. nsCOMPtr<nsIContentViewer> viewer;
  7047. mOSHE->GetContentViewer(getter_AddRefs(viewer));
  7048. if (viewer) {
  7049. NS_WARNING("mOSHE already has a content viewer!");
  7050. return false;
  7051. }
  7052. // Only save presentation for "normal" loads and link loads. Anything else
  7053. // probably wants to refetch the page, so caching the old presentation
  7054. // would be incorrect.
  7055. if (aLoadType != LOAD_NORMAL &&
  7056. aLoadType != LOAD_HISTORY &&
  7057. aLoadType != LOAD_LINK &&
  7058. aLoadType != LOAD_STOP_CONTENT &&
  7059. aLoadType != LOAD_STOP_CONTENT_AND_REPLACE &&
  7060. aLoadType != LOAD_ERROR_PAGE) {
  7061. return false;
  7062. }
  7063. // If the session history entry has the saveLayoutState flag set to false,
  7064. // then we should not cache the presentation.
  7065. bool canSaveState;
  7066. mOSHE->GetSaveLayoutStateFlag(&canSaveState);
  7067. if (!canSaveState) {
  7068. return false;
  7069. }
  7070. // If the document is not done loading, don't cache it.
  7071. if (!mScriptGlobal || mScriptGlobal->IsLoading()) {
  7072. return false;
  7073. }
  7074. if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) {
  7075. return false;
  7076. }
  7077. // Avoid doing the work of saving the presentation state in the case where
  7078. // the content viewer cache is disabled.
  7079. if (nsSHistory::GetMaxTotalViewers() == 0) {
  7080. return false;
  7081. }
  7082. // Don't cache the content viewer if we're in a subframe and the subframe
  7083. // pref is disabled.
  7084. bool cacheFrames =
  7085. Preferences::GetBool("browser.sessionhistory.cache_subframes", false);
  7086. if (!cacheFrames) {
  7087. nsCOMPtr<nsIDocShellTreeItem> root;
  7088. GetSameTypeParent(getter_AddRefs(root));
  7089. if (root && root != this) {
  7090. return false; // this is a subframe load
  7091. }
  7092. }
  7093. // If the document does not want its presentation cached, then don't.
  7094. nsCOMPtr<nsIDocument> doc = mScriptGlobal->GetExtantDoc();
  7095. return doc && doc->CanSavePresentation(aNewRequest);
  7096. }
  7097. void
  7098. nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry)
  7099. {
  7100. NS_ASSERTION(!mEditorData,
  7101. "Why reattach an editor when we already have one?");
  7102. NS_ASSERTION(aSHEntry && aSHEntry->HasDetachedEditor(),
  7103. "Reattaching when there's not a detached editor.");
  7104. if (mEditorData || !aSHEntry) {
  7105. return;
  7106. }
  7107. mEditorData = aSHEntry->ForgetEditorData();
  7108. if (mEditorData) {
  7109. #ifdef DEBUG
  7110. nsresult rv =
  7111. #endif
  7112. mEditorData->ReattachToWindow(this);
  7113. NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to reattach editing session");
  7114. }
  7115. }
  7116. void
  7117. nsDocShell::DetachEditorFromWindow()
  7118. {
  7119. if (!mEditorData || mEditorData->WaitingForLoad()) {
  7120. // If there's nothing to detach, or if the editor data is actually set
  7121. // up for the _new_ page that's coming in, don't detach.
  7122. return;
  7123. }
  7124. NS_ASSERTION(!mOSHE || !mOSHE->HasDetachedEditor(),
  7125. "Detaching editor when it's already detached.");
  7126. nsresult res = mEditorData->DetachFromWindow();
  7127. NS_ASSERTION(NS_SUCCEEDED(res), "Failed to detach editor");
  7128. if (NS_SUCCEEDED(res)) {
  7129. // Make mOSHE hold the owning ref to the editor data.
  7130. if (mOSHE) {
  7131. mOSHE->SetEditorData(mEditorData.forget());
  7132. } else {
  7133. mEditorData = nullptr;
  7134. }
  7135. }
  7136. #ifdef DEBUG
  7137. {
  7138. bool isEditable;
  7139. GetEditable(&isEditable);
  7140. NS_ASSERTION(!isEditable,
  7141. "Window is still editable after detaching editor.");
  7142. }
  7143. #endif // DEBUG
  7144. }
  7145. nsresult
  7146. nsDocShell::CaptureState()
  7147. {
  7148. if (!mOSHE || mOSHE == mLSHE) {
  7149. // No entry to save into, or we're replacing the existing entry.
  7150. return NS_ERROR_FAILURE;
  7151. }
  7152. if (!mScriptGlobal) {
  7153. return NS_ERROR_FAILURE;
  7154. }
  7155. nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState();
  7156. NS_ENSURE_TRUE(windowState, NS_ERROR_FAILURE);
  7157. #ifdef DEBUG_PAGE_CACHE
  7158. nsCOMPtr<nsIURI> uri;
  7159. mOSHE->GetURI(getter_AddRefs(uri));
  7160. nsAutoCString spec;
  7161. if (uri) {
  7162. uri->GetSpec(spec);
  7163. }
  7164. printf("Saving presentation into session history\n");
  7165. printf(" SH URI: %s\n", spec.get());
  7166. #endif
  7167. nsresult rv = mOSHE->SetWindowState(windowState);
  7168. NS_ENSURE_SUCCESS(rv, rv);
  7169. // Suspend refresh URIs and save off the timer queue
  7170. rv = mOSHE->SetRefreshURIList(mSavedRefreshURIList);
  7171. NS_ENSURE_SUCCESS(rv, rv);
  7172. // Capture the current content viewer bounds.
  7173. if (mContentViewer) {
  7174. nsIntRect bounds;
  7175. mContentViewer->GetBounds(bounds);
  7176. rv = mOSHE->SetViewerBounds(bounds);
  7177. NS_ENSURE_SUCCESS(rv, rv);
  7178. }
  7179. // Capture the docshell hierarchy.
  7180. mOSHE->ClearChildShells();
  7181. uint32_t childCount = mChildList.Length();
  7182. for (uint32_t i = 0; i < childCount; ++i) {
  7183. nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i));
  7184. NS_ASSERTION(childShell, "null child shell");
  7185. mOSHE->AddChildShell(childShell);
  7186. }
  7187. return NS_OK;
  7188. }
  7189. NS_IMETHODIMP
  7190. nsDocShell::RestorePresentationEvent::Run()
  7191. {
  7192. if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())) {
  7193. NS_WARNING("RestoreFromHistory failed");
  7194. }
  7195. return NS_OK;
  7196. }
  7197. NS_IMETHODIMP
  7198. nsDocShell::BeginRestore(nsIContentViewer* aContentViewer, bool aTop)
  7199. {
  7200. nsresult rv;
  7201. if (!aContentViewer) {
  7202. rv = EnsureContentViewer();
  7203. NS_ENSURE_SUCCESS(rv, rv);
  7204. aContentViewer = mContentViewer;
  7205. }
  7206. // Dispatch events for restoring the presentation. We try to simulate
  7207. // the progress notifications loading the document would cause, so we add
  7208. // the document's channel to the loadgroup to initiate stateChange
  7209. // notifications.
  7210. nsCOMPtr<nsIDOMDocument> domDoc;
  7211. aContentViewer->GetDOMDocument(getter_AddRefs(domDoc));
  7212. nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
  7213. if (doc) {
  7214. nsIChannel* channel = doc->GetChannel();
  7215. if (channel) {
  7216. mEODForCurrentDocument = false;
  7217. mIsRestoringDocument = true;
  7218. mLoadGroup->AddRequest(channel, nullptr);
  7219. mIsRestoringDocument = false;
  7220. }
  7221. }
  7222. if (!aTop) {
  7223. // This point corresponds to us having gotten OnStartRequest or
  7224. // STATE_START, so do the same thing that CreateContentViewer does at
  7225. // this point to ensure that unload/pagehide events for this document
  7226. // will fire when it's unloaded again.
  7227. mFiredUnloadEvent = false;
  7228. // For non-top frames, there is no notion of making sure that the
  7229. // previous document is in the domwindow when STATE_START notifications
  7230. // happen. We can just call BeginRestore for all of the child shells
  7231. // now.
  7232. rv = BeginRestoreChildren();
  7233. NS_ENSURE_SUCCESS(rv, rv);
  7234. }
  7235. return NS_OK;
  7236. }
  7237. nsresult
  7238. nsDocShell::BeginRestoreChildren()
  7239. {
  7240. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  7241. while (iter.HasMore()) {
  7242. nsCOMPtr<nsIDocShell> child = do_QueryObject(iter.GetNext());
  7243. if (child) {
  7244. nsresult rv = child->BeginRestore(nullptr, false);
  7245. NS_ENSURE_SUCCESS(rv, rv);
  7246. }
  7247. }
  7248. return NS_OK;
  7249. }
  7250. NS_IMETHODIMP
  7251. nsDocShell::FinishRestore()
  7252. {
  7253. // First we call finishRestore() on our children. In the simulated load,
  7254. // all of the child frames finish loading before the main document.
  7255. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  7256. while (iter.HasMore()) {
  7257. nsCOMPtr<nsIDocShell> child = do_QueryObject(iter.GetNext());
  7258. if (child) {
  7259. child->FinishRestore();
  7260. }
  7261. }
  7262. if (mOSHE && mOSHE->HasDetachedEditor()) {
  7263. ReattachEditorToWindow(mOSHE);
  7264. }
  7265. nsCOMPtr<nsIDocument> doc = GetDocument();
  7266. if (doc) {
  7267. // Finally, we remove the request from the loadgroup. This will
  7268. // cause onStateChange(STATE_STOP) to fire, which will fire the
  7269. // pageshow event to the chrome.
  7270. nsIChannel* channel = doc->GetChannel();
  7271. if (channel) {
  7272. mIsRestoringDocument = true;
  7273. mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
  7274. mIsRestoringDocument = false;
  7275. }
  7276. }
  7277. return NS_OK;
  7278. }
  7279. NS_IMETHODIMP
  7280. nsDocShell::GetRestoringDocument(bool* aRestoring)
  7281. {
  7282. *aRestoring = mIsRestoringDocument;
  7283. return NS_OK;
  7284. }
  7285. nsresult
  7286. nsDocShell::RestorePresentation(nsISHEntry* aSHEntry, bool* aRestoring)
  7287. {
  7288. NS_ASSERTION(mLoadType & LOAD_CMD_HISTORY,
  7289. "RestorePresentation should only be called for history loads");
  7290. nsCOMPtr<nsIContentViewer> viewer;
  7291. aSHEntry->GetContentViewer(getter_AddRefs(viewer));
  7292. #ifdef DEBUG_PAGE_CACHE
  7293. nsCOMPtr<nsIURI> uri;
  7294. aSHEntry->GetURI(getter_AddRefs(uri));
  7295. nsAutoCString spec;
  7296. if (uri) {
  7297. uri->GetSpec(spec);
  7298. }
  7299. #endif
  7300. *aRestoring = false;
  7301. if (!viewer) {
  7302. #ifdef DEBUG_PAGE_CACHE
  7303. printf("no saved presentation for uri: %s\n", spec.get());
  7304. #endif
  7305. return NS_OK;
  7306. }
  7307. // We need to make sure the content viewer's container is this docshell.
  7308. // In subframe navigation, it's possible for the docshell that the
  7309. // content viewer was originally loaded into to be replaced with a
  7310. // different one. We don't currently support restoring the presentation
  7311. // in that case.
  7312. nsCOMPtr<nsIDocShell> container;
  7313. viewer->GetContainer(getter_AddRefs(container));
  7314. if (!::SameCOMIdentity(container, GetAsSupports(this))) {
  7315. #ifdef DEBUG_PAGE_CACHE
  7316. printf("No valid container, clearing presentation\n");
  7317. #endif
  7318. aSHEntry->SetContentViewer(nullptr);
  7319. return NS_ERROR_FAILURE;
  7320. }
  7321. NS_ASSERTION(mContentViewer != viewer, "Restoring existing presentation");
  7322. #ifdef DEBUG_PAGE_CACHE
  7323. printf("restoring presentation from session history: %s\n", spec.get());
  7324. #endif
  7325. SetHistoryEntry(&mLSHE, aSHEntry);
  7326. // Post an event that will remove the request after we've returned
  7327. // to the event loop. This mimics the way it is called by nsIChannel
  7328. // implementations.
  7329. // Revoke any pending restore (just in case)
  7330. NS_ASSERTION(!mRestorePresentationEvent.IsPending(),
  7331. "should only have one RestorePresentationEvent");
  7332. mRestorePresentationEvent.Revoke();
  7333. RefPtr<RestorePresentationEvent> evt = new RestorePresentationEvent(this);
  7334. nsresult rv = NS_DispatchToCurrentThread(evt);
  7335. if (NS_SUCCEEDED(rv)) {
  7336. mRestorePresentationEvent = evt.get();
  7337. // The rest of the restore processing will happen on our event
  7338. // callback.
  7339. *aRestoring = true;
  7340. }
  7341. return rv;
  7342. }
  7343. namespace {
  7344. class MOZ_STACK_CLASS PresentationEventForgetter
  7345. {
  7346. public:
  7347. explicit PresentationEventForgetter(
  7348. nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
  7349. aRestorePresentationEvent)
  7350. : mRestorePresentationEvent(aRestorePresentationEvent)
  7351. , mEvent(aRestorePresentationEvent.get())
  7352. {
  7353. }
  7354. ~PresentationEventForgetter()
  7355. {
  7356. Forget();
  7357. }
  7358. void Forget()
  7359. {
  7360. if (mRestorePresentationEvent.get() == mEvent) {
  7361. mRestorePresentationEvent.Forget();
  7362. mEvent = nullptr;
  7363. }
  7364. }
  7365. private:
  7366. nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
  7367. mRestorePresentationEvent;
  7368. RefPtr<nsDocShell::RestorePresentationEvent> mEvent;
  7369. };
  7370. } // namespace
  7371. nsresult
  7372. nsDocShell::RestoreFromHistory()
  7373. {
  7374. MOZ_ASSERT(mRestorePresentationEvent.IsPending());
  7375. PresentationEventForgetter forgetter(mRestorePresentationEvent);
  7376. // This section of code follows the same ordering as CreateContentViewer.
  7377. if (!mLSHE) {
  7378. return NS_ERROR_FAILURE;
  7379. }
  7380. nsCOMPtr<nsIContentViewer> viewer;
  7381. mLSHE->GetContentViewer(getter_AddRefs(viewer));
  7382. if (!viewer) {
  7383. return NS_ERROR_FAILURE;
  7384. }
  7385. if (mSavingOldViewer) {
  7386. // We determined that it was safe to cache the document presentation
  7387. // at the time we initiated the new load. We need to check whether
  7388. // it's still safe to do so, since there may have been DOM mutations
  7389. // or new requests initiated.
  7390. nsCOMPtr<nsIDOMDocument> domDoc;
  7391. viewer->GetDOMDocument(getter_AddRefs(domDoc));
  7392. nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
  7393. nsIRequest* request = nullptr;
  7394. if (doc) {
  7395. request = doc->GetChannel();
  7396. }
  7397. mSavingOldViewer = CanSavePresentation(mLoadType, request, doc);
  7398. }
  7399. nsCOMPtr<nsIContentViewer> oldCv(mContentViewer);
  7400. nsCOMPtr<nsIContentViewer> newCv(viewer);
  7401. int32_t minFontSize = 0;
  7402. float textZoom = 1.0f;
  7403. float pageZoom = 1.0f;
  7404. float overrideDPPX = 0.0f;
  7405. bool styleDisabled = false;
  7406. if (oldCv && newCv) {
  7407. oldCv->GetMinFontSize(&minFontSize);
  7408. oldCv->GetTextZoom(&textZoom);
  7409. oldCv->GetFullZoom(&pageZoom);
  7410. oldCv->GetOverrideDPPX(&overrideDPPX);
  7411. oldCv->GetAuthorStyleDisabled(&styleDisabled);
  7412. }
  7413. // Protect against mLSHE going away via a load triggered from
  7414. // pagehide or unload.
  7415. nsCOMPtr<nsISHEntry> origLSHE = mLSHE;
  7416. // Make sure to blow away our mLoadingURI just in case. No loads
  7417. // from inside this pagehide.
  7418. mLoadingURI = nullptr;
  7419. // Notify the old content viewer that it's being hidden.
  7420. FirePageHideNotification(!mSavingOldViewer);
  7421. // If mLSHE was changed as a result of the pagehide event, then
  7422. // something else was loaded. Don't finish restoring.
  7423. if (mLSHE != origLSHE) {
  7424. return NS_OK;
  7425. }
  7426. // Add the request to our load group. We do this before swapping out
  7427. // the content viewers so that consumers of STATE_START can access
  7428. // the old document. We only deal with the toplevel load at this time --
  7429. // to be consistent with normal document loading, subframes cannot start
  7430. // loading until after data arrives, which is after STATE_START completes.
  7431. RefPtr<RestorePresentationEvent> currentPresentationRestoration =
  7432. mRestorePresentationEvent.get();
  7433. Stop();
  7434. // Make sure we're still restoring the same presentation.
  7435. // If we aren't, docshell is in process doing another load already.
  7436. NS_ENSURE_STATE(currentPresentationRestoration ==
  7437. mRestorePresentationEvent.get());
  7438. BeginRestore(viewer, true);
  7439. NS_ENSURE_STATE(currentPresentationRestoration ==
  7440. mRestorePresentationEvent.get());
  7441. forgetter.Forget();
  7442. // Set mFiredUnloadEvent = false so that the unload handler for the
  7443. // *new* document will fire.
  7444. mFiredUnloadEvent = false;
  7445. mURIResultedInDocument = true;
  7446. nsCOMPtr<nsISHistory> rootSH;
  7447. GetRootSessionHistory(getter_AddRefs(rootSH));
  7448. if (rootSH) {
  7449. nsCOMPtr<nsISHistoryInternal> hist = do_QueryInterface(rootSH);
  7450. rootSH->GetIndex(&mPreviousTransIndex);
  7451. hist->UpdateIndex();
  7452. rootSH->GetIndex(&mLoadedTransIndex);
  7453. #ifdef DEBUG_PAGE_CACHE
  7454. printf("Previous index: %d, Loaded index: %d\n\n", mPreviousTransIndex,
  7455. mLoadedTransIndex);
  7456. #endif
  7457. }
  7458. // Rather than call Embed(), we will retrieve the viewer from the session
  7459. // history entry and swap it in.
  7460. // XXX can we refactor this so that we can just call Embed()?
  7461. PersistLayoutHistoryState();
  7462. nsresult rv;
  7463. if (mContentViewer) {
  7464. if (mSavingOldViewer && NS_FAILED(CaptureState())) {
  7465. if (mOSHE) {
  7466. mOSHE->SyncPresentationState();
  7467. }
  7468. mSavingOldViewer = false;
  7469. }
  7470. }
  7471. mSavedRefreshURIList = nullptr;
  7472. // In cases where we use a transient about:blank viewer between loads,
  7473. // we never show the transient viewer, so _its_ previous viewer is never
  7474. // unhooked from the view hierarchy. Destroy any such previous viewer now,
  7475. // before we grab the root view sibling, so that we don't grab a view
  7476. // that's about to go away.
  7477. if (mContentViewer) {
  7478. nsCOMPtr<nsIContentViewer> previousViewer;
  7479. mContentViewer->GetPreviousViewer(getter_AddRefs(previousViewer));
  7480. if (previousViewer) {
  7481. mContentViewer->SetPreviousViewer(nullptr);
  7482. previousViewer->Destroy();
  7483. }
  7484. }
  7485. // Save off the root view's parent and sibling so that we can insert the
  7486. // new content viewer's root view at the same position. Also save the
  7487. // bounds of the root view's widget.
  7488. nsView* rootViewSibling = nullptr;
  7489. nsView* rootViewParent = nullptr;
  7490. nsIntRect newBounds(0, 0, 0, 0);
  7491. nsCOMPtr<nsIPresShell> oldPresShell = GetPresShell();
  7492. if (oldPresShell) {
  7493. nsViewManager* vm = oldPresShell->GetViewManager();
  7494. if (vm) {
  7495. nsView* oldRootView = vm->GetRootView();
  7496. if (oldRootView) {
  7497. rootViewSibling = oldRootView->GetNextSibling();
  7498. rootViewParent = oldRootView->GetParent();
  7499. mContentViewer->GetBounds(newBounds);
  7500. }
  7501. }
  7502. }
  7503. nsCOMPtr<nsIContent> container;
  7504. nsCOMPtr<nsIDocument> sibling;
  7505. if (rootViewParent && rootViewParent->GetParent()) {
  7506. nsIFrame* frame = rootViewParent->GetParent()->GetFrame();
  7507. container = frame ? frame->GetContent() : nullptr;
  7508. }
  7509. if (rootViewSibling) {
  7510. nsIFrame* frame = rootViewSibling->GetFrame();
  7511. sibling =
  7512. frame ? frame->PresContext()->PresShell()->GetDocument() : nullptr;
  7513. }
  7514. // Transfer ownership to mContentViewer. By ensuring that either the
  7515. // docshell or the session history, but not both, have references to the
  7516. // content viewer, we prevent the viewer from being torn down after
  7517. // Destroy() is called.
  7518. if (mContentViewer) {
  7519. mContentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
  7520. viewer->SetPreviousViewer(mContentViewer);
  7521. }
  7522. if (mOSHE && (!mContentViewer || !mSavingOldViewer)) {
  7523. // We don't plan to save a viewer in mOSHE; tell it to drop
  7524. // any other state it's holding.
  7525. mOSHE->SyncPresentationState();
  7526. }
  7527. // Order the mContentViewer setup just like Embed does.
  7528. mContentViewer = nullptr;
  7529. // Now that we're about to switch documents, forget all of our children.
  7530. // Note that we cached them as needed up in CaptureState above.
  7531. DestroyChildren();
  7532. mContentViewer.swap(viewer);
  7533. // Grab all of the related presentation from the SHEntry now.
  7534. // Clearing the viewer from the SHEntry will clear all of this state.
  7535. nsCOMPtr<nsISupports> windowState;
  7536. mLSHE->GetWindowState(getter_AddRefs(windowState));
  7537. mLSHE->SetWindowState(nullptr);
  7538. bool sticky;
  7539. mLSHE->GetSticky(&sticky);
  7540. nsCOMPtr<nsIDOMDocument> domDoc;
  7541. mContentViewer->GetDOMDocument(getter_AddRefs(domDoc));
  7542. nsCOMArray<nsIDocShellTreeItem> childShells;
  7543. int32_t i = 0;
  7544. nsCOMPtr<nsIDocShellTreeItem> child;
  7545. while (NS_SUCCEEDED(mLSHE->ChildShellAt(i++, getter_AddRefs(child))) &&
  7546. child) {
  7547. childShells.AppendObject(child);
  7548. }
  7549. // get the previous content viewer size
  7550. nsIntRect oldBounds(0, 0, 0, 0);
  7551. mLSHE->GetViewerBounds(oldBounds);
  7552. // Restore the refresh URI list. The refresh timers will be restarted
  7553. // when EndPageLoad() is called.
  7554. nsCOMPtr<nsIMutableArray> refreshURIList;
  7555. mLSHE->GetRefreshURIList(getter_AddRefs(refreshURIList));
  7556. // Reattach to the window object.
  7557. mIsRestoringDocument = true; // for MediaDocument::BecomeInteractive
  7558. rv = mContentViewer->Open(windowState, mLSHE);
  7559. mIsRestoringDocument = false;
  7560. // Hack to keep nsDocShellEditorData alive across the
  7561. // SetContentViewer(nullptr) call below.
  7562. nsAutoPtr<nsDocShellEditorData> data(mLSHE->ForgetEditorData());
  7563. // Now remove it from the cached presentation.
  7564. mLSHE->SetContentViewer(nullptr);
  7565. mEODForCurrentDocument = false;
  7566. mLSHE->SetEditorData(data.forget());
  7567. #ifdef DEBUG
  7568. {
  7569. nsCOMPtr<nsIMutableArray> refreshURIs;
  7570. mLSHE->GetRefreshURIList(getter_AddRefs(refreshURIs));
  7571. nsCOMPtr<nsIDocShellTreeItem> childShell;
  7572. mLSHE->ChildShellAt(0, getter_AddRefs(childShell));
  7573. NS_ASSERTION(!refreshURIs && !childShell,
  7574. "SHEntry should have cleared presentation state");
  7575. }
  7576. #endif
  7577. // Restore the sticky state of the viewer. The viewer has set this state
  7578. // on the history entry in Destroy() just before marking itself non-sticky,
  7579. // to avoid teardown of the presentation.
  7580. mContentViewer->SetSticky(sticky);
  7581. NS_ENSURE_SUCCESS(rv, rv);
  7582. // mLSHE is now our currently-loaded document.
  7583. SetHistoryEntry(&mOSHE, mLSHE);
  7584. // XXX special wyciwyg handling in Embed()?
  7585. // We aren't going to restore any items from the LayoutHistoryState,
  7586. // but we don't want them to stay around in case the page is reloaded.
  7587. SetLayoutHistoryState(nullptr);
  7588. // This is the end of our Embed() replacement
  7589. mSavingOldViewer = false;
  7590. mEODForCurrentDocument = false;
  7591. // Tell the event loop to favor plevents over user events, see comments
  7592. // in CreateContentViewer.
  7593. if (++gNumberOfDocumentsLoading == 1) {
  7594. FavorPerformanceHint(true);
  7595. }
  7596. if (oldCv && newCv) {
  7597. newCv->SetMinFontSize(minFontSize);
  7598. newCv->SetTextZoom(textZoom);
  7599. newCv->SetFullZoom(pageZoom);
  7600. newCv->SetOverrideDPPX(overrideDPPX);
  7601. newCv->SetAuthorStyleDisabled(styleDisabled);
  7602. }
  7603. nsCOMPtr<nsIDocument> document = do_QueryInterface(domDoc);
  7604. if (document) {
  7605. RefPtr<nsDocShell> parent = GetParentDocshell();
  7606. if (parent) {
  7607. nsCOMPtr<nsIDocument> d = parent->GetDocument();
  7608. if (d) {
  7609. if (d->EventHandlingSuppressed()) {
  7610. document->SuppressEventHandling(nsIDocument::eEvents,
  7611. d->EventHandlingSuppressed());
  7612. }
  7613. // Ick, it'd be nicer to not rewalk all of the subdocs here.
  7614. if (d->AnimationsPaused()) {
  7615. document->SuppressEventHandling(nsIDocument::eAnimationsOnly,
  7616. d->AnimationsPaused());
  7617. }
  7618. }
  7619. }
  7620. // Use the uri from the mLSHE we had when we entered this function
  7621. // (which need not match the document's URI if anchors are involved),
  7622. // since that's the history entry we're loading. Note that if we use
  7623. // origLSHE we don't have to worry about whether the entry in question
  7624. // is still mLSHE or whether it's now mOSHE.
  7625. nsCOMPtr<nsIURI> uri;
  7626. origLSHE->GetURI(getter_AddRefs(uri));
  7627. SetCurrentURI(uri, document->GetChannel(), true, 0);
  7628. }
  7629. // This is the end of our CreateContentViewer() replacement.
  7630. // Now we simulate a load. First, we restore the state of the javascript
  7631. // window object.
  7632. nsCOMPtr<nsPIDOMWindowOuter> privWin = GetWindow();
  7633. NS_ASSERTION(privWin, "could not get nsPIDOMWindow interface");
  7634. // Now, dispatch a title change event which would happen as the
  7635. // <head> is parsed.
  7636. document->NotifyPossibleTitleChange(false);
  7637. // Now we simulate appending child docshells for subframes.
  7638. for (i = 0; i < childShells.Count(); ++i) {
  7639. nsIDocShellTreeItem* childItem = childShells.ObjectAt(i);
  7640. nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem);
  7641. // Make sure to not clobber the state of the child. Since AddChild
  7642. // always clobbers it, save it off first.
  7643. bool allowPlugins;
  7644. childShell->GetAllowPlugins(&allowPlugins);
  7645. bool allowJavascript;
  7646. childShell->GetAllowJavascript(&allowJavascript);
  7647. bool allowRedirects;
  7648. childShell->GetAllowMetaRedirects(&allowRedirects);
  7649. bool allowSubframes;
  7650. childShell->GetAllowSubframes(&allowSubframes);
  7651. bool allowImages;
  7652. childShell->GetAllowImages(&allowImages);
  7653. bool allowMedia = childShell->GetAllowMedia();
  7654. bool allowDNSPrefetch;
  7655. childShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
  7656. bool allowContentRetargeting = childShell->GetAllowContentRetargeting();
  7657. bool allowContentRetargetingOnChildren =
  7658. childShell->GetAllowContentRetargetingOnChildren();
  7659. uint32_t defaultLoadFlags;
  7660. childShell->GetDefaultLoadFlags(&defaultLoadFlags);
  7661. // this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that
  7662. // the child inherits our state. Among other things, this means that the
  7663. // child inherits our mIsActive, mIsPrerendered and mPrivateBrowsingId,
  7664. // which is what we want.
  7665. AddChild(childItem);
  7666. childShell->SetAllowPlugins(allowPlugins);
  7667. childShell->SetAllowJavascript(allowJavascript);
  7668. childShell->SetAllowMetaRedirects(allowRedirects);
  7669. childShell->SetAllowSubframes(allowSubframes);
  7670. childShell->SetAllowImages(allowImages);
  7671. childShell->SetAllowMedia(allowMedia);
  7672. childShell->SetAllowDNSPrefetch(allowDNSPrefetch);
  7673. childShell->SetAllowContentRetargeting(allowContentRetargeting);
  7674. childShell->SetAllowContentRetargetingOnChildren(
  7675. allowContentRetargetingOnChildren);
  7676. childShell->SetDefaultLoadFlags(defaultLoadFlags);
  7677. rv = childShell->BeginRestore(nullptr, false);
  7678. NS_ENSURE_SUCCESS(rv, rv);
  7679. }
  7680. // Make sure to restore the window state after adding the child shells back
  7681. // to the tree. This is necessary for Thaw() and Resume() to propagate
  7682. // properly.
  7683. rv = privWin->RestoreWindowState(windowState);
  7684. NS_ENSURE_SUCCESS(rv, rv);
  7685. nsCOMPtr<nsIPresShell> shell = GetPresShell();
  7686. // We may be displayed on a different monitor (or in a different
  7687. // HiDPI mode) than when we got into the history list. So we need
  7688. // to check if this has happened. See bug 838239.
  7689. // Because the prescontext normally handles resolution changes via
  7690. // a runnable (see nsPresContext::UIResolutionChanged), its device
  7691. // context won't be -immediately- updated as a result of calling
  7692. // shell->BackingScaleFactorChanged().
  7693. // But we depend on that device context when adjusting the view size
  7694. // via mContentViewer->SetBounds(newBounds) below. So we need to
  7695. // explicitly tell it to check for changed resolution here.
  7696. if (shell && shell->GetPresContext()->DeviceContext()->CheckDPIChange()) {
  7697. shell->BackingScaleFactorChanged();
  7698. }
  7699. nsViewManager* newVM = shell ? shell->GetViewManager() : nullptr;
  7700. nsView* newRootView = newVM ? newVM->GetRootView() : nullptr;
  7701. // Insert the new root view at the correct location in the view tree.
  7702. if (container) {
  7703. nsSubDocumentFrame* subDocFrame =
  7704. do_QueryFrame(container->GetPrimaryFrame());
  7705. rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr;
  7706. } else {
  7707. rootViewParent = nullptr;
  7708. }
  7709. if (sibling &&
  7710. sibling->GetShell() &&
  7711. sibling->GetShell()->GetViewManager()) {
  7712. rootViewSibling = sibling->GetShell()->GetViewManager()->GetRootView();
  7713. } else {
  7714. rootViewSibling = nullptr;
  7715. }
  7716. if (rootViewParent && newRootView &&
  7717. newRootView->GetParent() != rootViewParent) {
  7718. nsViewManager* parentVM = rootViewParent->GetViewManager();
  7719. if (parentVM) {
  7720. // InsertChild(parent, child, sib, true) inserts the child after
  7721. // sib in content order, which is before sib in view order. BUT
  7722. // when sib is null it inserts at the end of the the document
  7723. // order, i.e., first in view order. But when oldRootSibling is
  7724. // null, the old root as at the end of the view list --- last in
  7725. // content order --- and we want to call InsertChild(parent, child,
  7726. // nullptr, false) in that case.
  7727. parentVM->InsertChild(rootViewParent, newRootView,
  7728. rootViewSibling,
  7729. rootViewSibling ? true : false);
  7730. NS_ASSERTION(newRootView->GetNextSibling() == rootViewSibling,
  7731. "error in InsertChild");
  7732. }
  7733. }
  7734. nsCOMPtr<nsPIDOMWindowInner> privWinInner = privWin->GetCurrentInnerWindow();
  7735. // If parent is suspended, increase suspension count.
  7736. // This can't be done as early as event suppression since this
  7737. // depends on docshell tree.
  7738. privWinInner->SyncStateFromParentWindow();
  7739. // Now that all of the child docshells have been put into place, we can
  7740. // restart the timers for the window and all of the child frames.
  7741. privWinInner->Resume();
  7742. // Restore the refresh URI list. The refresh timers will be restarted
  7743. // when EndPageLoad() is called.
  7744. mRefreshURIList = refreshURIList;
  7745. // Meta-refresh timers have been restarted for this shell, but not
  7746. // for our children. Walk the child shells and restart their timers.
  7747. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
  7748. while (iter.HasMore()) {
  7749. nsCOMPtr<nsIDocShell> child = do_QueryObject(iter.GetNext());
  7750. if (child) {
  7751. child->ResumeRefreshURIs();
  7752. }
  7753. }
  7754. // Make sure this presentation is the same size as the previous
  7755. // presentation. If this is not the same size we showed it at last time,
  7756. // then we need to resize the widget.
  7757. // XXXbryner This interacts poorly with Firefox's infobar. If the old
  7758. // presentation had the infobar visible, then we will resize the new
  7759. // presentation to that smaller size. However, firing the locationchanged
  7760. // event will hide the infobar, which will immediately resize the window
  7761. // back to the larger size. A future optimization might be to restore
  7762. // the presentation at the "wrong" size, then fire the locationchanged
  7763. // event and check whether the docshell's new size is the same as the
  7764. // cached viewer size (skipping the resize if they are equal).
  7765. if (newRootView) {
  7766. if (!newBounds.IsEmpty() && !newBounds.IsEqualEdges(oldBounds)) {
  7767. #ifdef DEBUG_PAGE_CACHE
  7768. printf("resize widget(%d, %d, %d, %d)\n", newBounds.x,
  7769. newBounds.y, newBounds.width, newBounds.height);
  7770. #endif
  7771. mContentViewer->SetBounds(newBounds);
  7772. } else {
  7773. nsIScrollableFrame* rootScrollFrame =
  7774. shell->GetRootScrollFrameAsScrollableExternal();
  7775. if (rootScrollFrame) {
  7776. rootScrollFrame->PostScrolledAreaEventForCurrentArea();
  7777. }
  7778. }
  7779. }
  7780. // The FinishRestore call below can kill these, null them out so we don't
  7781. // have invalid pointer lying around.
  7782. newRootView = rootViewSibling = rootViewParent = nullptr;
  7783. newVM = nullptr;
  7784. // Simulate the completion of the load.
  7785. nsDocShell::FinishRestore();
  7786. // Restart plugins, and paint the content.
  7787. if (shell) {
  7788. shell->Thaw();
  7789. }
  7790. return privWin->FireDelayedDOMEvents();
  7791. }
  7792. nsresult
  7793. nsDocShell::CreateContentViewer(const nsACString& aContentType,
  7794. nsIRequest* aRequest,
  7795. nsIStreamListener** aContentHandler)
  7796. {
  7797. *aContentHandler = nullptr;
  7798. // Can we check the content type of the current content viewer
  7799. // and reuse it without destroying it and re-creating it?
  7800. NS_ASSERTION(mLoadGroup, "Someone ignored return from Init()?");
  7801. // Instantiate the content viewer object
  7802. nsCOMPtr<nsIContentViewer> viewer;
  7803. nsresult rv = NewContentViewerObj(aContentType, aRequest, mLoadGroup,
  7804. aContentHandler, getter_AddRefs(viewer));
  7805. if (NS_FAILED(rv)) {
  7806. return rv;
  7807. }
  7808. // Notify the current document that it is about to be unloaded!!
  7809. //
  7810. // It is important to fire the unload() notification *before* any state
  7811. // is changed within the DocShell - otherwise, javascript will get the
  7812. // wrong information :-(
  7813. //
  7814. if (mSavingOldViewer) {
  7815. // We determined that it was safe to cache the document presentation
  7816. // at the time we initiated the new load. We need to check whether
  7817. // it's still safe to do so, since there may have been DOM mutations
  7818. // or new requests initiated.
  7819. nsCOMPtr<nsIDOMDocument> domDoc;
  7820. viewer->GetDOMDocument(getter_AddRefs(domDoc));
  7821. nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
  7822. mSavingOldViewer = CanSavePresentation(mLoadType, aRequest, doc);
  7823. }
  7824. NS_ASSERTION(!mLoadingURI, "Re-entering unload?");
  7825. nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
  7826. if (aOpenedChannel) {
  7827. aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
  7828. }
  7829. FirePageHideNotification(!mSavingOldViewer);
  7830. mLoadingURI = nullptr;
  7831. // Set mFiredUnloadEvent = false so that the unload handler for the
  7832. // *new* document will fire.
  7833. mFiredUnloadEvent = false;
  7834. // we've created a new document so go ahead and call
  7835. // OnLoadingSite(), but don't fire OnLocationChange()
  7836. // notifications before we've called Embed(). See bug 284993.
  7837. mURIResultedInDocument = true;
  7838. if (mLoadType == LOAD_ERROR_PAGE) {
  7839. // We need to set the SH entry and our current URI here and not
  7840. // at the moment we load the page. We want the same behavior
  7841. // of Stop() as for a normal page load. See bug 514232 for details.
  7842. // Revert mLoadType to load type to state the page load failed,
  7843. // following function calls need it.
  7844. mLoadType = mFailedLoadType;
  7845. nsCOMPtr<nsIChannel> failedChannel = mFailedChannel;
  7846. nsIDocument* doc = viewer->GetDocument();
  7847. if (doc) {
  7848. doc->SetFailedChannel(failedChannel);
  7849. }
  7850. // Make sure we have a URI to set currentURI.
  7851. nsCOMPtr<nsIURI> failedURI;
  7852. nsCOMPtr<nsIPrincipal> triggeringPrincipal;
  7853. if (failedChannel) {
  7854. NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI));
  7855. } else {
  7856. // if there is no failed channel we have to explicitly provide
  7857. // a triggeringPrincipal for the history entry.
  7858. triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
  7859. }
  7860. if (!failedURI) {
  7861. failedURI = mFailedURI;
  7862. }
  7863. if (!failedURI) {
  7864. // We need a URI object to store a session history entry, so make up a URI
  7865. NS_NewURI(getter_AddRefs(failedURI), "about:blank");
  7866. }
  7867. // When we don't have failedURI, something wrong will happen. See
  7868. // bug 291876.
  7869. MOZ_ASSERT(failedURI, "We don't have a URI for history APIs.");
  7870. mFailedChannel = nullptr;
  7871. mFailedURI = nullptr;
  7872. // Create an shistory entry for the old load.
  7873. if (failedURI) {
  7874. bool errorOnLocationChangeNeeded = OnNewURI(
  7875. failedURI, failedChannel, triggeringPrincipal,
  7876. nullptr, mLoadType, false, false, false);
  7877. if (errorOnLocationChangeNeeded) {
  7878. FireOnLocationChange(this, failedChannel, failedURI,
  7879. LOCATION_CHANGE_ERROR_PAGE);
  7880. }
  7881. }
  7882. // Be sure to have a correct mLSHE, it may have been cleared by
  7883. // EndPageLoad. See bug 302115.
  7884. if (mSessionHistory && !mLSHE) {
  7885. int32_t idx;
  7886. mSessionHistory->GetRequestedIndex(&idx);
  7887. if (idx == -1) {
  7888. mSessionHistory->GetIndex(&idx);
  7889. }
  7890. mSessionHistory->GetEntryAtIndex(idx, false, getter_AddRefs(mLSHE));
  7891. }
  7892. mLoadType = LOAD_ERROR_PAGE;
  7893. }
  7894. bool onLocationChangeNeeded = OnLoadingSite(aOpenedChannel, false);
  7895. // let's try resetting the load group if we need to...
  7896. nsCOMPtr<nsILoadGroup> currentLoadGroup;
  7897. NS_ENSURE_SUCCESS(
  7898. aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup)),
  7899. NS_ERROR_FAILURE);
  7900. if (currentLoadGroup != mLoadGroup) {
  7901. nsLoadFlags loadFlags = 0;
  7902. // Cancel any URIs that are currently loading...
  7903. // XXX: Need to do this eventually Stop();
  7904. //
  7905. // Retarget the document to this loadgroup...
  7906. //
  7907. /* First attach the channel to the right loadgroup
  7908. * and then remove from the old loadgroup. This
  7909. * puts the notifications in the right order and
  7910. * we don't null-out mLSHE in OnStateChange() for
  7911. * all redirected urls
  7912. */
  7913. aOpenedChannel->SetLoadGroup(mLoadGroup);
  7914. // Mark the channel as being a document URI...
  7915. aOpenedChannel->GetLoadFlags(&loadFlags);
  7916. loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
  7917. aOpenedChannel->SetLoadFlags(loadFlags);
  7918. mLoadGroup->AddRequest(aRequest, nullptr);
  7919. if (currentLoadGroup) {
  7920. currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED);
  7921. }
  7922. // Update the notification callbacks, so that progress and
  7923. // status information are sent to the right docshell...
  7924. aOpenedChannel->SetNotificationCallbacks(this);
  7925. }
  7926. NS_ENSURE_SUCCESS(Embed(viewer, "", nullptr), NS_ERROR_FAILURE);
  7927. mSavedRefreshURIList = nullptr;
  7928. mSavingOldViewer = false;
  7929. mEODForCurrentDocument = false;
  7930. // if this document is part of a multipart document,
  7931. // the ID can be used to distinguish it from the other parts.
  7932. nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
  7933. if (multiPartChannel) {
  7934. nsCOMPtr<nsIPresShell> shell = GetPresShell();
  7935. if (NS_SUCCEEDED(rv) && shell) {
  7936. nsIDocument* doc = shell->GetDocument();
  7937. if (doc) {
  7938. uint32_t partID;
  7939. multiPartChannel->GetPartID(&partID);
  7940. doc->SetPartID(partID);
  7941. }
  7942. }
  7943. }
  7944. // Give hint to native plevent dispatch mechanism. If a document
  7945. // is loading the native plevent dispatch mechanism should favor
  7946. // performance over normal native event dispatch priorities.
  7947. if (++gNumberOfDocumentsLoading == 1) {
  7948. // Hint to favor performance for the plevent notification mechanism.
  7949. // We want the pages to load as fast as possible even if its means
  7950. // native messages might be starved.
  7951. FavorPerformanceHint(true);
  7952. }
  7953. if (onLocationChangeNeeded) {
  7954. FireOnLocationChange(this, aRequest, mCurrentURI, 0);
  7955. }
  7956. return NS_OK;
  7957. }
  7958. nsresult
  7959. nsDocShell::NewContentViewerObj(const nsACString& aContentType,
  7960. nsIRequest* aRequest, nsILoadGroup* aLoadGroup,
  7961. nsIStreamListener** aContentHandler,
  7962. nsIContentViewer** aViewer)
  7963. {
  7964. nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
  7965. nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
  7966. nsContentUtils::FindInternalContentViewer(aContentType);
  7967. if (!docLoaderFactory) {
  7968. return NS_ERROR_FAILURE;
  7969. }
  7970. // Now create an instance of the content viewer nsLayoutDLF makes the
  7971. // determination if it should be a "view-source" instead of "view"
  7972. nsresult rv = docLoaderFactory->CreateInstance("view",
  7973. aOpenedChannel,
  7974. aLoadGroup, aContentType,
  7975. this,
  7976. nullptr,
  7977. aContentHandler,
  7978. aViewer);
  7979. NS_ENSURE_SUCCESS(rv, rv);
  7980. (*aViewer)->SetContainer(this);
  7981. return NS_OK;
  7982. }
  7983. nsresult
  7984. nsDocShell::SetupNewViewer(nsIContentViewer* aNewViewer)
  7985. {
  7986. //
  7987. // Copy content viewer state from previous or parent content viewer.
  7988. //
  7989. // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad!
  7990. //
  7991. // Do NOT to maintain a reference to the old content viewer outside
  7992. // of this "copying" block, or it will not be destroyed until the end of
  7993. // this routine and all <SCRIPT>s and event handlers fail! (bug 20315)
  7994. //
  7995. // In this block of code, if we get an error result, we return it
  7996. // but if we get a null pointer, that's perfectly legal for parent
  7997. // and parentContentViewer.
  7998. //
  7999. int32_t x = 0;
  8000. int32_t y = 0;
  8001. int32_t cx = 0;
  8002. int32_t cy = 0;
  8003. // This will get the size from the current content viewer or from the
  8004. // Init settings
  8005. DoGetPositionAndSize(&x, &y, &cx, &cy);
  8006. nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
  8007. NS_ENSURE_SUCCESS(GetSameTypeParent(getter_AddRefs(parentAsItem)),
  8008. NS_ERROR_FAILURE);
  8009. nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
  8010. nsAutoCString forceCharset;
  8011. nsAutoCString hintCharset;
  8012. int32_t hintCharsetSource;
  8013. int32_t minFontSize;
  8014. float textZoom;
  8015. float pageZoom;
  8016. float overrideDPPX;
  8017. bool styleDisabled;
  8018. // |newMUDV| also serves as a flag to set the data from the above vars
  8019. nsCOMPtr<nsIContentViewer> newCv;
  8020. if (mContentViewer || parent) {
  8021. nsCOMPtr<nsIContentViewer> oldCv;
  8022. if (mContentViewer) {
  8023. // Get any interesting state from old content viewer
  8024. // XXX: it would be far better to just reuse the document viewer ,
  8025. // since we know we're just displaying the same document as before
  8026. oldCv = mContentViewer;
  8027. // Tell the old content viewer to hibernate in session history when
  8028. // it is destroyed.
  8029. if (mSavingOldViewer && NS_FAILED(CaptureState())) {
  8030. if (mOSHE) {
  8031. mOSHE->SyncPresentationState();
  8032. }
  8033. mSavingOldViewer = false;
  8034. }
  8035. } else {
  8036. // No old content viewer, so get state from parent's content viewer
  8037. parent->GetContentViewer(getter_AddRefs(oldCv));
  8038. }
  8039. if (oldCv) {
  8040. newCv = aNewViewer;
  8041. if (newCv) {
  8042. NS_ENSURE_SUCCESS(oldCv->GetForceCharacterSet(forceCharset),
  8043. NS_ERROR_FAILURE);
  8044. NS_ENSURE_SUCCESS(oldCv->GetHintCharacterSet(hintCharset),
  8045. NS_ERROR_FAILURE);
  8046. NS_ENSURE_SUCCESS(oldCv->GetHintCharacterSetSource(&hintCharsetSource),
  8047. NS_ERROR_FAILURE);
  8048. NS_ENSURE_SUCCESS(oldCv->GetMinFontSize(&minFontSize),
  8049. NS_ERROR_FAILURE);
  8050. NS_ENSURE_SUCCESS(oldCv->GetTextZoom(&textZoom),
  8051. NS_ERROR_FAILURE);
  8052. NS_ENSURE_SUCCESS(oldCv->GetFullZoom(&pageZoom),
  8053. NS_ERROR_FAILURE);
  8054. NS_ENSURE_SUCCESS(oldCv->GetOverrideDPPX(&overrideDPPX),
  8055. NS_ERROR_FAILURE);
  8056. NS_ENSURE_SUCCESS(oldCv->GetAuthorStyleDisabled(&styleDisabled),
  8057. NS_ERROR_FAILURE);
  8058. }
  8059. }
  8060. }
  8061. nscolor bgcolor = NS_RGBA(0, 0, 0, 0);
  8062. // Ensure that the content viewer is destroyed *after* the GC - bug 71515
  8063. nsCOMPtr<nsIContentViewer> contentViewer = mContentViewer;
  8064. if (contentViewer) {
  8065. // Stop any activity that may be happening in the old document before
  8066. // releasing it...
  8067. contentViewer->Stop();
  8068. // Try to extract the canvas background color from the old
  8069. // presentation shell, so we can use it for the next document.
  8070. nsCOMPtr<nsIPresShell> shell;
  8071. contentViewer->GetPresShell(getter_AddRefs(shell));
  8072. if (shell) {
  8073. bgcolor = shell->GetCanvasBackground();
  8074. }
  8075. contentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
  8076. aNewViewer->SetPreviousViewer(contentViewer);
  8077. }
  8078. if (mOSHE && (!mContentViewer || !mSavingOldViewer)) {
  8079. // We don't plan to save a viewer in mOSHE; tell it to drop
  8080. // any other state it's holding.
  8081. mOSHE->SyncPresentationState();
  8082. }
  8083. mContentViewer = nullptr;
  8084. // Now that we're about to switch documents, forget all of our children.
  8085. // Note that we cached them as needed up in CaptureState above.
  8086. DestroyChildren();
  8087. mContentViewer = aNewViewer;
  8088. nsCOMPtr<nsIWidget> widget;
  8089. NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(widget)), NS_ERROR_FAILURE);
  8090. nsIntRect bounds(x, y, cx, cy);
  8091. mContentViewer->SetNavigationTiming(mTiming);
  8092. if (NS_FAILED(mContentViewer->Init(widget, bounds))) {
  8093. nsCOMPtr<nsIContentViewer> viewer = mContentViewer;
  8094. viewer->Close(nullptr);
  8095. viewer->Destroy();
  8096. mContentViewer = nullptr;
  8097. mCurrentURI = nullptr;
  8098. NS_WARNING("ContentViewer Initialization failed");
  8099. return NS_ERROR_FAILURE;
  8100. }
  8101. // If we have old state to copy, set the old state onto the new content
  8102. // viewer
  8103. if (newCv) {
  8104. NS_ENSURE_SUCCESS(newCv->SetForceCharacterSet(forceCharset),
  8105. NS_ERROR_FAILURE);
  8106. NS_ENSURE_SUCCESS(newCv->SetHintCharacterSet(hintCharset),
  8107. NS_ERROR_FAILURE);
  8108. NS_ENSURE_SUCCESS(newCv->SetHintCharacterSetSource(hintCharsetSource),
  8109. NS_ERROR_FAILURE);
  8110. NS_ENSURE_SUCCESS(newCv->SetMinFontSize(minFontSize),
  8111. NS_ERROR_FAILURE);
  8112. NS_ENSURE_SUCCESS(newCv->SetTextZoom(textZoom),
  8113. NS_ERROR_FAILURE);
  8114. NS_ENSURE_SUCCESS(newCv->SetFullZoom(pageZoom),
  8115. NS_ERROR_FAILURE);
  8116. NS_ENSURE_SUCCESS(newCv->SetOverrideDPPX(overrideDPPX),
  8117. NS_ERROR_FAILURE);
  8118. NS_ENSURE_SUCCESS(newCv->SetAuthorStyleDisabled(styleDisabled),
  8119. NS_ERROR_FAILURE);
  8120. }
  8121. // Stuff the bgcolor from the old pres shell into the new
  8122. // pres shell. This improves page load continuity.
  8123. nsCOMPtr<nsIPresShell> shell;
  8124. mContentViewer->GetPresShell(getter_AddRefs(shell));
  8125. if (shell) {
  8126. shell->SetCanvasBackground(bgcolor);
  8127. }
  8128. // XXX: It looks like the LayoutState gets restored again in Embed()
  8129. // right after the call to SetupNewViewer(...)
  8130. // We don't show the mContentViewer yet, since we want to draw the old page
  8131. // until we have enough of the new page to show. Just return with the new
  8132. // viewer still set to hidden.
  8133. return NS_OK;
  8134. }
  8135. nsresult
  8136. nsDocShell::SetDocCurrentStateObj(nsISHEntry* aShEntry)
  8137. {
  8138. NS_ENSURE_STATE(mContentViewer);
  8139. nsCOMPtr<nsIDocument> document = GetDocument();
  8140. NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
  8141. nsCOMPtr<nsIStructuredCloneContainer> scContainer;
  8142. if (aShEntry) {
  8143. nsresult rv = aShEntry->GetStateData(getter_AddRefs(scContainer));
  8144. NS_ENSURE_SUCCESS(rv, rv);
  8145. // If aShEntry is null, just set the document's state object to null.
  8146. }
  8147. // It's OK for scContainer too be null here; that just means there's no
  8148. // state data associated with this history entry.
  8149. document->SetStateObject(scContainer);
  8150. return NS_OK;
  8151. }
  8152. nsresult
  8153. nsDocShell::CheckLoadingPermissions()
  8154. {
  8155. // This method checks whether the caller may load content into
  8156. // this docshell. Even though we've done our best to hide windows
  8157. // from code that doesn't have the right to access them, it's
  8158. // still possible for an evil site to open a window and access
  8159. // frames in the new window through window.frames[] (which is
  8160. // allAccess for historic reasons), so we still need to do this
  8161. // check on load.
  8162. nsresult rv = NS_OK;
  8163. if (!gValidateOrigin || !IsFrame()) {
  8164. // Origin validation was turned off, or we're not a frame.
  8165. // Permit all loads.
  8166. return rv;
  8167. }
  8168. // Note - The check for a current JSContext here isn't necessarily sensical.
  8169. // It's just designed to preserve the old semantics during a mass-conversion
  8170. // patch.
  8171. if (!nsContentUtils::GetCurrentJSContext()) {
  8172. return NS_OK;
  8173. }
  8174. // Check if the caller is from the same origin as this docshell,
  8175. // or any of its ancestors.
  8176. nsCOMPtr<nsIDocShellTreeItem> item(this);
  8177. do {
  8178. nsCOMPtr<nsIScriptGlobalObject> sgo = do_GetInterface(item);
  8179. nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo));
  8180. nsIPrincipal* p;
  8181. if (!sop || !(p = sop->GetPrincipal())) {
  8182. return NS_ERROR_UNEXPECTED;
  8183. }
  8184. if (nsContentUtils::SubjectPrincipal()->Subsumes(p)) {
  8185. // Same origin, permit load
  8186. return NS_OK;
  8187. }
  8188. nsCOMPtr<nsIDocShellTreeItem> tmp;
  8189. item->GetSameTypeParent(getter_AddRefs(tmp));
  8190. item.swap(tmp);
  8191. } while (item);
  8192. return NS_ERROR_DOM_PROP_ACCESS_DENIED;
  8193. }
  8194. //*****************************************************************************
  8195. // nsDocShell: Site Loading
  8196. //*****************************************************************************
  8197. namespace {
  8198. #ifdef MOZ_PLACES
  8199. // Callback used by CopyFavicon to inform the favicon service that one URI
  8200. // (mNewURI) has the same favicon URI (OnComplete's aFaviconURI) as another.
  8201. class nsCopyFaviconCallback final : public nsIFaviconDataCallback
  8202. {
  8203. public:
  8204. NS_DECL_ISUPPORTS
  8205. nsCopyFaviconCallback(mozIAsyncFavicons* aSvc,
  8206. nsIURI* aNewURI,
  8207. nsIPrincipal* aLoadingPrincipal,
  8208. bool aInPrivateBrowsing)
  8209. : mSvc(aSvc)
  8210. , mNewURI(aNewURI)
  8211. , mLoadingPrincipal(aLoadingPrincipal)
  8212. , mInPrivateBrowsing(aInPrivateBrowsing)
  8213. {
  8214. }
  8215. NS_IMETHOD
  8216. OnComplete(nsIURI* aFaviconURI, uint32_t aDataLen,
  8217. const uint8_t* aData, const nsACString& aMimeType) override
  8218. {
  8219. // Continue only if there is an associated favicon.
  8220. if (!aFaviconURI) {
  8221. return NS_OK;
  8222. }
  8223. MOZ_ASSERT(aDataLen == 0,
  8224. "We weren't expecting the callback to deliver data.");
  8225. nsCOMPtr<mozIPlacesPendingOperation> po;
  8226. return mSvc->SetAndFetchFaviconForPage(
  8227. mNewURI, aFaviconURI, false,
  8228. mInPrivateBrowsing ? nsIFaviconService::FAVICON_LOAD_PRIVATE :
  8229. nsIFaviconService::FAVICON_LOAD_NON_PRIVATE,
  8230. nullptr, mLoadingPrincipal, getter_AddRefs(po));
  8231. }
  8232. private:
  8233. ~nsCopyFaviconCallback() {}
  8234. nsCOMPtr<mozIAsyncFavicons> mSvc;
  8235. nsCOMPtr<nsIURI> mNewURI;
  8236. nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
  8237. bool mInPrivateBrowsing;
  8238. };
  8239. NS_IMPL_ISUPPORTS(nsCopyFaviconCallback, nsIFaviconDataCallback)
  8240. #endif
  8241. } // namespace
  8242. void
  8243. nsDocShell::CopyFavicon(nsIURI* aOldURI,
  8244. nsIURI* aNewURI,
  8245. nsIPrincipal* aLoadingPrincipal,
  8246. bool aInPrivateBrowsing)
  8247. {
  8248. if (XRE_IsContentProcess()) {
  8249. dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
  8250. if (contentChild) {
  8251. mozilla::ipc::URIParams oldURI, newURI;
  8252. SerializeURI(aOldURI, oldURI);
  8253. SerializeURI(aNewURI, newURI);
  8254. contentChild->SendCopyFavicon(oldURI, newURI,
  8255. IPC::Principal(aLoadingPrincipal),
  8256. aInPrivateBrowsing);
  8257. }
  8258. return;
  8259. }
  8260. #ifdef MOZ_PLACES
  8261. nsCOMPtr<mozIAsyncFavicons> favSvc =
  8262. do_GetService("@mozilla.org/browser/favicon-service;1");
  8263. if (favSvc) {
  8264. nsCOMPtr<nsIFaviconDataCallback> callback =
  8265. new nsCopyFaviconCallback(favSvc, aNewURI,
  8266. aLoadingPrincipal,
  8267. aInPrivateBrowsing);
  8268. favSvc->GetFaviconURLForPage(aOldURI, callback);
  8269. }
  8270. #endif
  8271. }
  8272. class InternalLoadEvent : public Runnable
  8273. {
  8274. public:
  8275. InternalLoadEvent(nsDocShell* aDocShell, nsIURI* aURI,
  8276. nsIURI* aOriginalURI, bool aLoadReplace,
  8277. bool aIsFromProcessingFrameAttributes,
  8278. nsIURI* aReferrer, uint32_t aReferrerPolicy,
  8279. nsIPrincipal* aTriggeringPrincipal,
  8280. nsIPrincipal* aPrincipalToInherit, uint32_t aFlags,
  8281. const char* aTypeHint, nsIInputStream* aPostData,
  8282. nsIInputStream* aHeadersData, uint32_t aLoadType,
  8283. nsISHEntry* aSHEntry, bool aFirstParty,
  8284. const nsAString& aSrcdoc, nsIDocShell* aSourceDocShell,
  8285. nsIURI* aBaseURI)
  8286. : mSrcdoc(aSrcdoc)
  8287. , mDocShell(aDocShell)
  8288. , mURI(aURI)
  8289. , mOriginalURI(aOriginalURI)
  8290. , mLoadReplace(aLoadReplace)
  8291. , mIsFromProcessingFrameAttributes(aIsFromProcessingFrameAttributes)
  8292. , mReferrer(aReferrer)
  8293. , mReferrerPolicy(aReferrerPolicy)
  8294. , mTriggeringPrincipal(aTriggeringPrincipal)
  8295. , mPrincipalToInherit(aPrincipalToInherit)
  8296. , mPostData(aPostData)
  8297. , mHeadersData(aHeadersData)
  8298. , mSHEntry(aSHEntry)
  8299. , mFlags(aFlags)
  8300. , mLoadType(aLoadType)
  8301. , mFirstParty(aFirstParty)
  8302. , mSourceDocShell(aSourceDocShell)
  8303. , mBaseURI(aBaseURI)
  8304. {
  8305. // Make sure to keep null things null as needed
  8306. if (aTypeHint) {
  8307. mTypeHint = aTypeHint;
  8308. }
  8309. }
  8310. NS_IMETHOD
  8311. Run() override
  8312. {
  8313. return mDocShell->InternalLoad(mURI, mOriginalURI,
  8314. mLoadReplace,
  8315. mIsFromProcessingFrameAttributes,
  8316. mReferrer,
  8317. mReferrerPolicy,
  8318. mTriggeringPrincipal, mPrincipalToInherit,
  8319. mFlags, EmptyString(), mTypeHint.get(),
  8320. NullString(), mPostData, mHeadersData,
  8321. mLoadType, mSHEntry, mFirstParty,
  8322. mSrcdoc, mSourceDocShell, mBaseURI,
  8323. nullptr, nullptr);
  8324. }
  8325. private:
  8326. // Use IDL strings so .get() returns null by default
  8327. nsXPIDLString mWindowTarget;
  8328. nsXPIDLCString mTypeHint;
  8329. nsString mSrcdoc;
  8330. RefPtr<nsDocShell> mDocShell;
  8331. nsCOMPtr<nsIURI> mURI;
  8332. nsCOMPtr<nsIURI> mOriginalURI;
  8333. bool mLoadReplace;
  8334. bool mIsFromProcessingFrameAttributes;
  8335. nsCOMPtr<nsIURI> mReferrer;
  8336. uint32_t mReferrerPolicy;
  8337. nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
  8338. nsCOMPtr<nsIPrincipal> mPrincipalToInherit;
  8339. nsCOMPtr<nsIInputStream> mPostData;
  8340. nsCOMPtr<nsIInputStream> mHeadersData;
  8341. nsCOMPtr<nsISHEntry> mSHEntry;
  8342. uint32_t mFlags;
  8343. uint32_t mLoadType;
  8344. bool mFirstParty;
  8345. nsCOMPtr<nsIDocShell> mSourceDocShell;
  8346. nsCOMPtr<nsIURI> mBaseURI;
  8347. };
  8348. /**
  8349. * Returns true if we started an asynchronous load (i.e., from the network), but
  8350. * the document we're loading there hasn't yet become this docshell's active
  8351. * document.
  8352. *
  8353. * When JustStartedNetworkLoad is true, you should be careful about modifying
  8354. * mLoadType and mLSHE. These are both set when the asynchronous load first
  8355. * starts, and the load expects that, when it eventually runs InternalLoad,
  8356. * mLoadType and mLSHE will have their original values.
  8357. */
  8358. bool
  8359. nsDocShell::JustStartedNetworkLoad()
  8360. {
  8361. return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel();
  8362. }
  8363. nsresult
  8364. nsDocShell::CreatePrincipalFromReferrer(nsIURI* aReferrer,
  8365. nsIPrincipal** aResult)
  8366. {
  8367. PrincipalOriginAttributes attrs;
  8368. attrs.InheritFromDocShellToDoc(mOriginAttributes, aReferrer);
  8369. nsCOMPtr<nsIPrincipal> prin =
  8370. BasePrincipal::CreateCodebasePrincipal(aReferrer, attrs);
  8371. prin.forget(aResult);
  8372. return *aResult ? NS_OK : NS_ERROR_FAILURE;
  8373. }
  8374. bool
  8375. nsDocShell::IsAboutNewtab(nsIURI* aURI)
  8376. {
  8377. if (!aURI) {
  8378. return false;
  8379. }
  8380. bool isAbout;
  8381. if (NS_WARN_IF(NS_FAILED(aURI->SchemeIs("about", &isAbout)))) {
  8382. return false;
  8383. }
  8384. if (!isAbout) {
  8385. return false;
  8386. }
  8387. nsAutoCString module;
  8388. if (NS_WARN_IF(NS_FAILED(NS_GetAboutModuleName(aURI, module)))) {
  8389. return false;
  8390. }
  8391. return module.Equals("newtab");
  8392. }
  8393. NS_IMETHODIMP
  8394. nsDocShell::InternalLoad(nsIURI* aURI,
  8395. nsIURI* aOriginalURI,
  8396. bool aLoadReplace,
  8397. bool aIsFromProcessingFrameAttributes,
  8398. nsIURI* aReferrer,
  8399. uint32_t aReferrerPolicy,
  8400. nsIPrincipal* aTriggeringPrincipal,
  8401. nsIPrincipal* aPrincipalToInherit,
  8402. uint32_t aFlags,
  8403. const nsAString& aWindowTarget,
  8404. const char* aTypeHint,
  8405. const nsAString& aFileName,
  8406. nsIInputStream* aPostData,
  8407. nsIInputStream* aHeadersData,
  8408. uint32_t aLoadType,
  8409. nsISHEntry* aSHEntry,
  8410. bool aFirstParty,
  8411. const nsAString& aSrcdoc,
  8412. nsIDocShell* aSourceDocShell,
  8413. nsIURI* aBaseURI,
  8414. nsIDocShell** aDocShell,
  8415. nsIRequest** aRequest)
  8416. {
  8417. MOZ_ASSERT(aTriggeringPrincipal, "need a valid TriggeringPrincipal");
  8418. nsresult rv = NS_OK;
  8419. mOriginalUriString.Truncate();
  8420. if (gDocShellLeakLog && MOZ_LOG_TEST(gDocShellLeakLog, LogLevel::Debug)) {
  8421. PR_LogPrint("DOCSHELL %p InternalLoad %s\n",
  8422. this, aURI ? aURI->GetSpecOrDefault().get() : "");
  8423. }
  8424. // Initialize aDocShell/aRequest
  8425. if (aDocShell) {
  8426. *aDocShell = nullptr;
  8427. }
  8428. if (aRequest) {
  8429. *aRequest = nullptr;
  8430. }
  8431. if (!aURI) {
  8432. return NS_ERROR_NULL_POINTER;
  8433. }
  8434. NS_ENSURE_TRUE(IsValidLoadType(aLoadType), NS_ERROR_INVALID_ARG);
  8435. NS_ENSURE_TRUE(!mIsBeingDestroyed, NS_ERROR_NOT_AVAILABLE);
  8436. rv = EnsureScriptEnvironment();
  8437. if (NS_FAILED(rv)) {
  8438. return rv;
  8439. }
  8440. // wyciwyg urls can only be loaded through history. Any normal load of
  8441. // wyciwyg through docshell is illegal. Disallow such loads.
  8442. if (aLoadType & LOAD_CMD_NORMAL) {
  8443. bool isWyciwyg = false;
  8444. rv = aURI->SchemeIs("wyciwyg", &isWyciwyg);
  8445. if ((isWyciwyg && NS_SUCCEEDED(rv)) || NS_FAILED(rv)) {
  8446. return NS_ERROR_FAILURE;
  8447. }
  8448. }
  8449. bool isJavaScript = false;
  8450. if (NS_FAILED(aURI->SchemeIs("javascript", &isJavaScript))) {
  8451. isJavaScript = false;
  8452. }
  8453. bool isTargetTopLevelDocShell = false;
  8454. nsCOMPtr<nsIDocShell> targetDocShell;
  8455. if (!aWindowTarget.IsEmpty()) {
  8456. // Locate the target DocShell.
  8457. nsCOMPtr<nsIDocShellTreeItem> targetItem;
  8458. // Only _self, _parent, and _top are supported in noopener case. But we
  8459. // have to be careful to not apply that to the noreferrer case. See bug
  8460. // 1358469.
  8461. bool allowNamedTarget = !(aFlags & INTERNAL_LOAD_FLAGS_NO_OPENER) ||
  8462. (aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
  8463. if (allowNamedTarget ||
  8464. aWindowTarget.LowerCaseEqualsLiteral("_self") ||
  8465. aWindowTarget.LowerCaseEqualsLiteral("_parent") ||
  8466. aWindowTarget.LowerCaseEqualsLiteral("_top")) {
  8467. rv = FindItemWithName(aWindowTarget, nullptr, this,
  8468. getter_AddRefs(targetItem));
  8469. NS_ENSURE_SUCCESS(rv, rv);
  8470. }
  8471. targetDocShell = do_QueryInterface(targetItem);
  8472. if (targetDocShell) {
  8473. // If the targetDocShell and the rootDocShell are the same, then the
  8474. // targetDocShell is the top level document and hence we should
  8475. // consider this TYPE_DOCUMENT
  8476. //
  8477. // For example:
  8478. // 1. target="_top"
  8479. // 2. target="_parent", where this docshell is in the 2nd level of
  8480. // docshell tree.
  8481. nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
  8482. targetDocShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
  8483. NS_ASSERTION(sameTypeRoot,
  8484. "No document shell root tree item from targetDocShell!");
  8485. nsCOMPtr<nsIDocShell> rootShell = do_QueryInterface(sameTypeRoot);
  8486. NS_ASSERTION(rootShell,
  8487. "No root docshell from document shell root tree item.");
  8488. isTargetTopLevelDocShell = targetDocShell == rootShell;
  8489. } else {
  8490. // If the targetDocShell doesn't exist, then this is a new docShell
  8491. // and we should consider this a TYPE_DOCUMENT load
  8492. //
  8493. // For example, when target="_blank"
  8494. isTargetTopLevelDocShell = true;
  8495. }
  8496. }
  8497. // The contentType will be INTERNAL_(I)FRAME if:
  8498. // 1. This docshell is for iframe.
  8499. // 2. AND aWindowTarget is not a new window, nor a top-level window.
  8500. //
  8501. // This variable will be used when we call NS_CheckContentLoadPolicy, and
  8502. // later when we call DoURILoad.
  8503. uint32_t contentType;
  8504. if (IsFrame() && !isTargetTopLevelDocShell) {
  8505. nsCOMPtr<Element> requestingElement =
  8506. mScriptGlobal->AsOuter()->GetFrameElementInternal();
  8507. if (requestingElement) {
  8508. contentType = requestingElement->IsHTMLElement(nsGkAtoms::iframe) ?
  8509. nsIContentPolicy::TYPE_INTERNAL_IFRAME : nsIContentPolicy::TYPE_INTERNAL_FRAME;
  8510. } else {
  8511. // If we have lost our frame element by now, just assume we're
  8512. // an iframe since that's more common.
  8513. contentType = nsIContentPolicy::TYPE_INTERNAL_IFRAME;
  8514. }
  8515. } else {
  8516. contentType = nsIContentPolicy::TYPE_DOCUMENT;
  8517. }
  8518. // If there's no targetDocShell, that means we are about to create a new
  8519. // window (or aWindowTarget is empty). Perform a content policy check before
  8520. // creating the window. Please note for all other docshell loads
  8521. // content policy checks are performed within the contentSecurityManager
  8522. // when the channel is about to be openend.
  8523. if (!targetDocShell && !aWindowTarget.IsEmpty()) {
  8524. MOZ_ASSERT(contentType == nsIContentPolicy::TYPE_DOCUMENT,
  8525. "opening a new window requires type to be TYPE_DOCUMENT");
  8526. nsISupports* requestingContext = nullptr;
  8527. if (XRE_IsContentProcess()) {
  8528. // In e10s the child process doesn't have access to the element that
  8529. // contains the browsing context (because that element is in the chrome
  8530. // process). So we just pass mScriptGlobal.
  8531. requestingContext = ToSupports(mScriptGlobal);
  8532. } else {
  8533. // This is for loading non-e10s tabs and toplevel windows of various
  8534. // sorts.
  8535. // For the toplevel window cases, requestingElement will be null.
  8536. nsCOMPtr<Element> requestingElement =
  8537. mScriptGlobal->AsOuter()->GetFrameElementInternal();
  8538. requestingContext = requestingElement;
  8539. }
  8540. // Since Content Policy checks are performed within docShell as well as
  8541. // the ContentSecurityManager we need a reliable way to let certain
  8542. // nsIContentPolicy consumers ignore duplicate calls. Let's use the 'extra'
  8543. // argument to pass a specific identifier.
  8544. nsCOMPtr<nsISupportsString> extraStr =
  8545. do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
  8546. NS_ENSURE_SUCCESS(rv, rv);
  8547. NS_NAMED_LITERAL_STRING(msg, "conPolCheckFromDocShell");
  8548. rv = extraStr->SetData(msg);
  8549. NS_ENSURE_SUCCESS(rv, rv);
  8550. int16_t shouldLoad = nsIContentPolicy::ACCEPT;
  8551. rv = NS_CheckContentLoadPolicy(contentType,
  8552. aURI,
  8553. aTriggeringPrincipal,
  8554. requestingContext,
  8555. EmptyCString(), // mime guess
  8556. extraStr, // extra
  8557. &shouldLoad);
  8558. if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
  8559. if (NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) {
  8560. return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
  8561. }
  8562. return NS_ERROR_CONTENT_BLOCKED;
  8563. }
  8564. }
  8565. nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
  8566. //
  8567. // Get a principal from the current document if necessary. Note that we only
  8568. // do this for URIs that inherit a security context and local file URIs;
  8569. // in particular we do NOT do this for about:blank. This way, random
  8570. // about:blank loads that have no principal (which basically means they were
  8571. // done by someone from chrome manually messing with our nsIWebNavigation
  8572. // or by C++ setting document.location) don't get a funky principal. If
  8573. // callers want something interesting to happen with the about:blank
  8574. // principal in this case, they should pass aPrincipalToInherit in.
  8575. //
  8576. {
  8577. bool inherits;
  8578. // One more twist: Don't inherit the principal for external loads.
  8579. if (aLoadType != LOAD_NORMAL_EXTERNAL && !principalToInherit &&
  8580. (aFlags & INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL) &&
  8581. NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(aURI,
  8582. &inherits)) &&
  8583. inherits) {
  8584. principalToInherit = GetInheritedPrincipal(true);
  8585. }
  8586. }
  8587. // Don't allow loads that would inherit our security context
  8588. // if this document came from an unsafe channel.
  8589. {
  8590. bool willInherit;
  8591. // This condition needs to match the one in
  8592. // nsContentUtils::ChannelShouldInheritPrincipal.
  8593. // Except we reverse the rv check to be safe in case
  8594. // nsContentUtils::URIInheritsSecurityContext fails here and
  8595. // succeeds there.
  8596. rv = nsContentUtils::URIInheritsSecurityContext(aURI, &willInherit);
  8597. if (NS_FAILED(rv) || willInherit || NS_IsAboutBlank(aURI)) {
  8598. nsCOMPtr<nsIDocShellTreeItem> treeItem = this;
  8599. do {
  8600. nsCOMPtr<nsIDocShell> itemDocShell = do_QueryInterface(treeItem);
  8601. bool isUnsafe;
  8602. if (itemDocShell &&
  8603. NS_SUCCEEDED(itemDocShell->GetChannelIsUnsafe(&isUnsafe)) &&
  8604. isUnsafe) {
  8605. return NS_ERROR_DOM_SECURITY_ERR;
  8606. }
  8607. nsCOMPtr<nsIDocShellTreeItem> parent;
  8608. treeItem->GetSameTypeParent(getter_AddRefs(parent));
  8609. parent.swap(treeItem);
  8610. } while (treeItem);
  8611. }
  8612. }
  8613. //
  8614. // Resolve the window target before going any further...
  8615. // If the load has been targeted to another DocShell, then transfer the
  8616. // load to it...
  8617. //
  8618. if (!aWindowTarget.IsEmpty()) {
  8619. // We've already done our owner-inheriting. Mask out that bit, so we
  8620. // don't try inheriting an owner from the target window if we came up
  8621. // with a null owner above.
  8622. aFlags = aFlags & ~INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL;
  8623. bool isNewWindow = false;
  8624. if (!targetDocShell) {
  8625. // If the docshell's document is sandboxed, only open a new window
  8626. // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set.
  8627. // (i.e. if allow-popups is specified)
  8628. NS_ENSURE_TRUE(mContentViewer, NS_ERROR_FAILURE);
  8629. nsIDocument* doc = mContentViewer->GetDocument();
  8630. uint32_t sandboxFlags = 0;
  8631. if (doc) {
  8632. sandboxFlags = doc->GetSandboxFlags();
  8633. if (sandboxFlags & SANDBOXED_AUXILIARY_NAVIGATION) {
  8634. return NS_ERROR_DOM_INVALID_ACCESS_ERR;
  8635. }
  8636. }
  8637. nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
  8638. NS_ENSURE_TRUE(win, NS_ERROR_NOT_AVAILABLE);
  8639. nsCOMPtr<nsPIDOMWindowOuter> newWin;
  8640. nsAutoCString spec;
  8641. if (aURI) {
  8642. aURI->GetSpec(spec);
  8643. }
  8644. // If we are a noopener load, we just hand the whole thing over to our
  8645. // window.
  8646. if (aFlags & INTERNAL_LOAD_FLAGS_NO_OPENER) {
  8647. // Various asserts that we know to hold because NO_OPENER loads can only
  8648. // happen for links.
  8649. MOZ_ASSERT(!aLoadReplace);
  8650. MOZ_ASSERT(aPrincipalToInherit == aTriggeringPrincipal);
  8651. MOZ_ASSERT(aFlags == INTERNAL_LOAD_FLAGS_NO_OPENER ||
  8652. aFlags == (INTERNAL_LOAD_FLAGS_NO_OPENER |
  8653. INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER));
  8654. MOZ_ASSERT(!aPostData);
  8655. MOZ_ASSERT(!aHeadersData);
  8656. MOZ_ASSERT(aLoadType == LOAD_LINK);
  8657. MOZ_ASSERT(!aSHEntry);
  8658. MOZ_ASSERT(aFirstParty); // Windowwatcher will assume this.
  8659. nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
  8660. rv = CreateLoadInfo(getter_AddRefs(loadInfo));
  8661. if (NS_FAILED(rv)) {
  8662. return rv;
  8663. }
  8664. // Set up our loadinfo so it will do the load as much like we would have
  8665. // as possible.
  8666. loadInfo->SetReferrer(aReferrer);
  8667. loadInfo->SetReferrerPolicy(aReferrerPolicy);
  8668. loadInfo->SetSendReferrer(!(aFlags &
  8669. INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER));
  8670. loadInfo->SetOriginalURI(aOriginalURI);
  8671. loadInfo->SetLoadReplace(aLoadReplace);
  8672. loadInfo->SetIsFromProcessingFrameAttributes(aIsFromProcessingFrameAttributes);
  8673. loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
  8674. loadInfo->SetInheritPrincipal(
  8675. aFlags & INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL);
  8676. // Explicit principal because we do not want any guesses as to what the
  8677. // principal to inherit is: it should be aTriggeringPrincipal.
  8678. loadInfo->SetPrincipalIsExplicit(true);
  8679. loadInfo->SetLoadType(ConvertLoadTypeToDocShellLoadInfo(LOAD_LINK));
  8680. loadInfo->SetForceAllowDataURI(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI);
  8681. rv = win->Open(NS_ConvertUTF8toUTF16(spec),
  8682. aWindowTarget, // window name
  8683. EmptyString(), // Features
  8684. loadInfo,
  8685. true, // aForceNoOpener
  8686. getter_AddRefs(newWin));
  8687. MOZ_ASSERT(!newWin);
  8688. return rv;
  8689. }
  8690. rv = win->OpenNoNavigate(NS_ConvertUTF8toUTF16(spec),
  8691. aWindowTarget, // window name
  8692. EmptyString(), // Features
  8693. getter_AddRefs(newWin));
  8694. // In some cases the Open call doesn't actually result in a new
  8695. // window being opened. We can detect these cases by examining the
  8696. // document in |newWin|, if any.
  8697. nsCOMPtr<nsPIDOMWindowOuter> piNewWin = do_QueryInterface(newWin);
  8698. if (piNewWin) {
  8699. nsCOMPtr<nsIDocument> newDoc = piNewWin->GetExtantDoc();
  8700. if (!newDoc || newDoc->IsInitialDocument()) {
  8701. isNewWindow = true;
  8702. aFlags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
  8703. }
  8704. }
  8705. nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(newWin);
  8706. targetDocShell = do_QueryInterface(webNav);
  8707. }
  8708. //
  8709. // Transfer the load to the target DocShell... Pass nullptr as the
  8710. // window target name from to prevent recursive retargeting!
  8711. //
  8712. if (NS_SUCCEEDED(rv) && targetDocShell) {
  8713. rv = targetDocShell->InternalLoad(aURI,
  8714. aOriginalURI,
  8715. aLoadReplace,
  8716. aIsFromProcessingFrameAttributes,
  8717. aReferrer,
  8718. aReferrerPolicy,
  8719. aTriggeringPrincipal,
  8720. principalToInherit,
  8721. aFlags,
  8722. EmptyString(), // No window target
  8723. aTypeHint,
  8724. NullString(), // No forced download
  8725. aPostData,
  8726. aHeadersData,
  8727. aLoadType,
  8728. aSHEntry,
  8729. aFirstParty,
  8730. aSrcdoc,
  8731. aSourceDocShell,
  8732. aBaseURI,
  8733. aDocShell,
  8734. aRequest);
  8735. if (rv == NS_ERROR_NO_CONTENT) {
  8736. // XXXbz except we never reach this code!
  8737. if (isNewWindow) {
  8738. //
  8739. // At this point, a new window has been created, but the
  8740. // URI did not have any data associated with it...
  8741. //
  8742. // So, the best we can do, is to tear down the new window
  8743. // that was just created!
  8744. //
  8745. if (nsCOMPtr<nsPIDOMWindowOuter> domWin = targetDocShell->GetWindow()) {
  8746. domWin->Close();
  8747. }
  8748. }
  8749. //
  8750. // NS_ERROR_NO_CONTENT should not be returned to the
  8751. // caller... This is an internal error code indicating that
  8752. // the URI had no data associated with it - probably a
  8753. // helper-app style protocol (ie. mailto://)
  8754. //
  8755. rv = NS_OK;
  8756. } else if (isNewWindow) {
  8757. // XXX: Once new windows are created hidden, the new
  8758. // window will need to be made visible... For now,
  8759. // do nothing.
  8760. }
  8761. }
  8762. // Else we ran out of memory, or were a popup and got blocked,
  8763. // or something.
  8764. return rv;
  8765. }
  8766. //
  8767. // Load is being targetted at this docshell so return an error if the
  8768. // docshell is in the process of being destroyed.
  8769. //
  8770. if (mIsBeingDestroyed) {
  8771. return NS_ERROR_FAILURE;
  8772. }
  8773. NS_ENSURE_STATE(!HasUnloadedParent());
  8774. rv = CheckLoadingPermissions();
  8775. if (NS_FAILED(rv)) {
  8776. return rv;
  8777. }
  8778. if (mFiredUnloadEvent) {
  8779. if (IsOKToLoadURI(aURI)) {
  8780. NS_PRECONDITION(aWindowTarget.IsEmpty(),
  8781. "Shouldn't have a window target here!");
  8782. // If this is a replace load, make whatever load triggered
  8783. // the unload event also a replace load, so we don't
  8784. // create extra history entries.
  8785. if (LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
  8786. mLoadType = LOAD_NORMAL_REPLACE;
  8787. }
  8788. // Do this asynchronously
  8789. nsCOMPtr<nsIRunnable> ev =
  8790. new InternalLoadEvent(this, aURI, aOriginalURI, aLoadReplace,
  8791. aIsFromProcessingFrameAttributes,
  8792. aReferrer, aReferrerPolicy,
  8793. aTriggeringPrincipal, principalToInherit,
  8794. aFlags, aTypeHint, aPostData, aHeadersData,
  8795. aLoadType, aSHEntry, aFirstParty, aSrcdoc,
  8796. aSourceDocShell, aBaseURI);
  8797. return NS_DispatchToCurrentThread(ev);
  8798. }
  8799. // Just ignore this load attempt
  8800. return NS_OK;
  8801. }
  8802. // If a source docshell has been passed, check to see if we are sandboxed
  8803. // from it as the result of an iframe or CSP sandbox.
  8804. if (aSourceDocShell && aSourceDocShell->IsSandboxedFrom(this)) {
  8805. return NS_ERROR_DOM_INVALID_ACCESS_ERR;
  8806. }
  8807. // If this docshell is owned by a frameloader, make sure to cancel
  8808. // possible frameloader initialization before loading a new page.
  8809. nsCOMPtr<nsIDocShellTreeItem> parent = GetParentDocshell();
  8810. if (parent) {
  8811. nsCOMPtr<nsIDocument> doc = parent->GetDocument();
  8812. if (doc) {
  8813. doc->TryCancelFrameLoaderInitialization(this);
  8814. }
  8815. }
  8816. bool loadFromExternal = false;
  8817. // Before going any further vet loads initiated by external programs.
  8818. if (aLoadType == LOAD_NORMAL_EXTERNAL) {
  8819. loadFromExternal = true;
  8820. // Disallow external chrome: loads targetted at content windows
  8821. bool isChrome = false;
  8822. if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome) {
  8823. NS_WARNING("blocked external chrome: url -- use '--chrome' option");
  8824. return NS_ERROR_FAILURE;
  8825. }
  8826. // clear the decks to prevent context bleed-through (bug 298255)
  8827. rv = CreateAboutBlankContentViewer(nullptr, nullptr);
  8828. if (NS_FAILED(rv)) {
  8829. return NS_ERROR_FAILURE;
  8830. }
  8831. // reset loadType so we don't have to add lots of tests for
  8832. // LOAD_NORMAL_EXTERNAL after this point
  8833. aLoadType = LOAD_NORMAL;
  8834. }
  8835. mAllowKeywordFixup =
  8836. (aFlags & INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) != 0;
  8837. mURIResultedInDocument = false; // reset the clock...
  8838. if (aLoadType == LOAD_NORMAL ||
  8839. aLoadType == LOAD_STOP_CONTENT ||
  8840. LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_REPLACE_HISTORY) ||
  8841. aLoadType == LOAD_HISTORY ||
  8842. aLoadType == LOAD_LINK) {
  8843. nsCOMPtr<nsIURI> currentURI = mCurrentURI;
  8844. nsAutoCString curHash, newHash;
  8845. bool curURIHasRef = false, newURIHasRef = false;
  8846. nsresult rvURINew = aURI->GetRef(newHash);
  8847. if (NS_SUCCEEDED(rvURINew)) {
  8848. rvURINew = aURI->GetHasRef(&newURIHasRef);
  8849. }
  8850. bool sameExceptHashes = false;
  8851. if (currentURI && NS_SUCCEEDED(rvURINew)) {
  8852. nsresult rvURIOld = currentURI->GetRef(curHash);
  8853. if (NS_SUCCEEDED(rvURIOld)) {
  8854. rvURIOld = currentURI->GetHasRef(&curURIHasRef);
  8855. }
  8856. if (NS_SUCCEEDED(rvURIOld)) {
  8857. if (NS_FAILED(currentURI->EqualsExceptRef(aURI, &sameExceptHashes))) {
  8858. sameExceptHashes = false;
  8859. }
  8860. }
  8861. }
  8862. if (!sameExceptHashes && sURIFixup && currentURI &&
  8863. NS_SUCCEEDED(rvURINew)) {
  8864. // Maybe aURI came from the exposable form of currentURI?
  8865. nsCOMPtr<nsIURI> currentExposableURI;
  8866. rv = sURIFixup->CreateExposableURI(currentURI,
  8867. getter_AddRefs(currentExposableURI));
  8868. NS_ENSURE_SUCCESS(rv, rv);
  8869. nsresult rvURIOld = currentExposableURI->GetRef(curHash);
  8870. if (NS_SUCCEEDED(rvURIOld)) {
  8871. rvURIOld = currentExposableURI->GetHasRef(&curURIHasRef);
  8872. }
  8873. if (NS_SUCCEEDED(rvURIOld)) {
  8874. if (NS_FAILED(currentExposableURI->EqualsExceptRef(aURI, &sameExceptHashes))) {
  8875. sameExceptHashes = false;
  8876. }
  8877. }
  8878. }
  8879. bool historyNavBetweenSameDoc = false;
  8880. if (mOSHE && aSHEntry) {
  8881. // We're doing a history load.
  8882. mOSHE->SharesDocumentWith(aSHEntry, &historyNavBetweenSameDoc);
  8883. #ifdef DEBUG
  8884. if (historyNavBetweenSameDoc) {
  8885. nsCOMPtr<nsIInputStream> currentPostData;
  8886. mOSHE->GetPostData(getter_AddRefs(currentPostData));
  8887. NS_ASSERTION(currentPostData == aPostData,
  8888. "Different POST data for entries for the same page?");
  8889. }
  8890. #endif
  8891. }
  8892. // A short-circuited load happens when we navigate between two SHEntries
  8893. // for the same document. We do a short-circuited load under two
  8894. // circumstances. Either
  8895. //
  8896. // a) we're navigating between two different SHEntries which share a
  8897. // document, or
  8898. //
  8899. // b) we're navigating to a new shentry whose URI differs from the
  8900. // current URI only in its hash, the new hash is non-empty, and
  8901. // we're not doing a POST.
  8902. //
  8903. // The restriction tha the SHEntries in (a) must be different ensures
  8904. // that history.go(0) and the like trigger full refreshes, rather than
  8905. // short-circuited loads.
  8906. bool doShortCircuitedLoad =
  8907. (historyNavBetweenSameDoc && mOSHE != aSHEntry) ||
  8908. (!aSHEntry && !aPostData &&
  8909. sameExceptHashes && newURIHasRef);
  8910. if (doShortCircuitedLoad) {
  8911. // Save the position of the scrollers.
  8912. nscoord cx = 0, cy = 0;
  8913. GetCurScrollPos(ScrollOrientation_X, &cx);
  8914. GetCurScrollPos(ScrollOrientation_Y, &cy);
  8915. // Reset mLoadType to its original value once we exit this block,
  8916. // because this short-circuited load might have started after a
  8917. // normal, network load, and we don't want to clobber its load type.
  8918. // See bug 737307.
  8919. AutoRestore<uint32_t> loadTypeResetter(mLoadType);
  8920. // If a non-short-circuit load (i.e., a network load) is pending,
  8921. // make this a replacement load, so that we don't add a SHEntry here
  8922. // and the network load goes into the SHEntry it expects to.
  8923. if (JustStartedNetworkLoad() && (aLoadType & LOAD_CMD_NORMAL)) {
  8924. mLoadType = LOAD_NORMAL_REPLACE;
  8925. } else {
  8926. mLoadType = aLoadType;
  8927. }
  8928. mURIResultedInDocument = true;
  8929. nsCOMPtr<nsISHEntry> oldLSHE = mLSHE;
  8930. /* we need to assign mLSHE to aSHEntry right here, so that on History
  8931. * loads, SetCurrentURI() called from OnNewURI() will send proper
  8932. * onLocationChange() notifications to the browser to update
  8933. * back/forward buttons.
  8934. */
  8935. SetHistoryEntry(&mLSHE, aSHEntry);
  8936. // Set the doc's URI according to the new history entry's URI.
  8937. nsCOMPtr<nsIDocument> doc = GetDocument();
  8938. NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
  8939. doc->SetDocumentURI(aURI);
  8940. /* This is a anchor traversal with in the same page.
  8941. * call OnNewURI() so that, this traversal will be
  8942. * recorded in session and global history.
  8943. */
  8944. nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit;
  8945. if (mOSHE) {
  8946. mOSHE->GetTriggeringPrincipal(getter_AddRefs(newURITriggeringPrincipal));
  8947. mOSHE->GetPrincipalToInherit(getter_AddRefs(newURIPrincipalToInherit));
  8948. } else {
  8949. newURITriggeringPrincipal = aTriggeringPrincipal;
  8950. newURIPrincipalToInherit = doc->NodePrincipal();
  8951. }
  8952. // Pass true for aCloneSHChildren, since we're not
  8953. // changing documents here, so all of our subframes are
  8954. // still relevant to the new session history entry.
  8955. //
  8956. // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT
  8957. // flag on firing onLocationChange(...).
  8958. // Anyway, aCloneSHChildren param is simply reflecting
  8959. // doShortCircuitedLoad in this scope.
  8960. OnNewURI(aURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit,
  8961. mLoadType, true, true, true);
  8962. nsCOMPtr<nsIInputStream> postData;
  8963. nsCOMPtr<nsISupports> cacheKey;
  8964. bool scrollRestorationIsManual = false;
  8965. if (mOSHE) {
  8966. /* save current position of scroller(s) (bug 59774) */
  8967. mOSHE->SetScrollPosition(cx, cy);
  8968. mOSHE->GetScrollRestorationIsManual(&scrollRestorationIsManual);
  8969. // Get the postdata and page ident from the current page, if
  8970. // the new load is being done via normal means. Note that
  8971. // "normal means" can be checked for just by checking for
  8972. // LOAD_CMD_NORMAL, given the loadType and allowScroll check
  8973. // above -- it filters out some LOAD_CMD_NORMAL cases that we
  8974. // wouldn't want here.
  8975. if (aLoadType & LOAD_CMD_NORMAL) {
  8976. mOSHE->GetPostData(getter_AddRefs(postData));
  8977. mOSHE->GetCacheKey(getter_AddRefs(cacheKey));
  8978. // Link our new SHEntry to the old SHEntry's back/forward
  8979. // cache data, since the two SHEntries correspond to the
  8980. // same document.
  8981. if (mLSHE) {
  8982. if (!aSHEntry) {
  8983. // If we're not doing a history load, scroll restoration
  8984. // should be inherited from the previous session history entry.
  8985. mLSHE->SetScrollRestorationIsManual(scrollRestorationIsManual);
  8986. }
  8987. mLSHE->AdoptBFCacheEntry(mOSHE);
  8988. }
  8989. }
  8990. }
  8991. // If we're doing a history load, use its scroll restoration state.
  8992. if (aSHEntry) {
  8993. aSHEntry->GetScrollRestorationIsManual(&scrollRestorationIsManual);
  8994. }
  8995. /* Assign mOSHE to mLSHE. This will either be a new entry created
  8996. * by OnNewURI() for normal loads or aSHEntry for history loads.
  8997. */
  8998. if (mLSHE) {
  8999. SetHistoryEntry(&mOSHE, mLSHE);
  9000. // Save the postData obtained from the previous page
  9001. // in to the session history entry created for the
  9002. // anchor page, so that any history load of the anchor
  9003. // page will restore the appropriate postData.
  9004. if (postData) {
  9005. mOSHE->SetPostData(postData);
  9006. }
  9007. // Make sure we won't just repost without hitting the
  9008. // cache first
  9009. if (cacheKey) {
  9010. mOSHE->SetCacheKey(cacheKey);
  9011. }
  9012. }
  9013. /* Restore the original LSHE if we were loading something
  9014. * while short-circuited load was initiated.
  9015. */
  9016. SetHistoryEntry(&mLSHE, oldLSHE);
  9017. /* Set the title for the SH entry for this target url. so that
  9018. * SH menus in go/back/forward buttons won't be empty for this.
  9019. */
  9020. if (mSessionHistory) {
  9021. int32_t index = -1;
  9022. mSessionHistory->GetIndex(&index);
  9023. nsCOMPtr<nsISHEntry> shEntry;
  9024. mSessionHistory->GetEntryAtIndex(index, false, getter_AddRefs(shEntry));
  9025. NS_ENSURE_TRUE(shEntry, NS_ERROR_FAILURE);
  9026. shEntry->SetTitle(mTitle);
  9027. }
  9028. /* Set the title for the Global History entry for this anchor url.
  9029. */
  9030. if (mUseGlobalHistory && !UsePrivateBrowsing()) {
  9031. nsCOMPtr<IHistory> history = services::GetHistoryService();
  9032. if (history) {
  9033. history->SetURITitle(aURI, mTitle);
  9034. } else if (mGlobalHistory) {
  9035. mGlobalHistory->SetPageTitle(aURI, mTitle);
  9036. }
  9037. }
  9038. SetDocCurrentStateObj(mOSHE);
  9039. // Inform the favicon service that the favicon for oldURI also
  9040. // applies to aURI.
  9041. CopyFavicon(currentURI, aURI, doc->NodePrincipal(), UsePrivateBrowsing());
  9042. RefPtr<nsGlobalWindow> scriptGlobal = mScriptGlobal;
  9043. RefPtr<nsGlobalWindow> win = scriptGlobal ?
  9044. scriptGlobal->GetCurrentInnerWindowInternal() : nullptr;
  9045. // ScrollToAnchor doesn't necessarily cause us to scroll the window;
  9046. // the function decides whether a scroll is appropriate based on the
  9047. // arguments it receives. But even if we don't end up scrolling,
  9048. // ScrollToAnchor performs other important tasks, such as informing
  9049. // the presShell that we have a new hash. See bug 680257.
  9050. rv = ScrollToAnchor(curURIHasRef, newURIHasRef, newHash, aLoadType);
  9051. NS_ENSURE_SUCCESS(rv, rv);
  9052. /* restore previous position of scroller(s), if we're moving
  9053. * back in history (bug 59774)
  9054. */
  9055. nscoord bx = 0;
  9056. nscoord by = 0;
  9057. bool needsScrollPosUpdate = false;
  9058. if (mOSHE && (aLoadType == LOAD_HISTORY ||
  9059. aLoadType == LOAD_RELOAD_NORMAL) &&
  9060. !scrollRestorationIsManual) {
  9061. needsScrollPosUpdate = true;
  9062. mOSHE->GetScrollPosition(&bx, &by);
  9063. }
  9064. // Dispatch the popstate and hashchange events, as appropriate.
  9065. //
  9066. // The event dispatch below can cause us to re-enter script and
  9067. // destroy the docshell, nulling out mScriptGlobal. Hold a stack
  9068. // reference to avoid null derefs. See bug 914521.
  9069. if (win) {
  9070. // Fire a hashchange event URIs differ, and only in their hashes.
  9071. bool doHashchange = sameExceptHashes &&
  9072. (curURIHasRef != newURIHasRef || !curHash.Equals(newHash));
  9073. if (historyNavBetweenSameDoc || doHashchange) {
  9074. win->DispatchSyncPopState();
  9075. }
  9076. if (needsScrollPosUpdate && win->AsInner()->HasActiveDocument()) {
  9077. SetCurScrollPosEx(bx, by);
  9078. }
  9079. if (doHashchange) {
  9080. // Note that currentURI hasn't changed because it's on the
  9081. // stack, so we can just use it directly as the old URI.
  9082. win->DispatchAsyncHashchange(currentURI, aURI);
  9083. }
  9084. }
  9085. return NS_OK;
  9086. }
  9087. }
  9088. // mContentViewer->PermitUnload can destroy |this| docShell, which
  9089. // causes the next call of CanSavePresentation to crash.
  9090. // Hold onto |this| until we return, to prevent a crash from happening.
  9091. // (bug#331040)
  9092. nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
  9093. // Don't init timing for javascript:, since it generally doesn't
  9094. // actually start a load or anything. If it does, we'll init
  9095. // timing then, from OnStateChange.
  9096. // XXXbz mTiming should know what channel it's for, so we don't
  9097. // need this hackery. Note that this is still broken in cases
  9098. // when we're loading something that's not javascript: and the
  9099. // beforeunload handler denies the load. That will screw up
  9100. // timing for the next load!
  9101. if (!isJavaScript) {
  9102. MaybeInitTiming();
  9103. }
  9104. bool timeBeforeUnload = aFileName.IsVoid();
  9105. if (mTiming && timeBeforeUnload) {
  9106. mTiming->NotifyBeforeUnload();
  9107. }
  9108. // Check if the page doesn't want to be unloaded. The javascript:
  9109. // protocol handler deals with this for javascript: URLs.
  9110. if (!isJavaScript && aFileName.IsVoid() && mContentViewer) {
  9111. bool okToUnload;
  9112. rv = mContentViewer->PermitUnload(&okToUnload);
  9113. if (NS_SUCCEEDED(rv) && !okToUnload) {
  9114. // The user chose not to unload the page, interrupt the
  9115. // load.
  9116. return NS_OK;
  9117. }
  9118. }
  9119. if (mTiming && timeBeforeUnload) {
  9120. mTiming->NotifyUnloadAccepted(mCurrentURI);
  9121. }
  9122. // Check if the webbrowser chrome wants the load to proceed; this can be
  9123. // used to cancel attempts to load URIs in the wrong process.
  9124. nsCOMPtr<nsIWebBrowserChrome3> browserChrome3 = do_GetInterface(mTreeOwner);
  9125. if (browserChrome3) {
  9126. // In case this is a remote newtab load, set aURI to aOriginalURI (newtab).
  9127. // This ensures that the verifySignedContent flag is set on loadInfo in
  9128. // DoURILoad.
  9129. nsIURI* uriForShouldLoadCheck = aURI;
  9130. if (IsAboutNewtab(aOriginalURI)) {
  9131. uriForShouldLoadCheck = aOriginalURI;
  9132. }
  9133. bool shouldLoad;
  9134. rv = browserChrome3->ShouldLoadURI(this, uriForShouldLoadCheck, aReferrer,
  9135. aTriggeringPrincipal, &shouldLoad);
  9136. if (NS_SUCCEEDED(rv) && !shouldLoad) {
  9137. return NS_OK;
  9138. }
  9139. }
  9140. // Whenever a top-level browsing context is navigated, the user agent MUST
  9141. // lock the orientation of the document to the document's default
  9142. // orientation. We don't explicitly check for a top-level browsing context
  9143. // here because orientation is only set on top-level browsing contexts.
  9144. // We make an exception for apps because they currently rely on
  9145. // orientation locks persisting across browsing contexts.
  9146. if (OrientationLock() != eScreenOrientation_None && !GetIsApp()) {
  9147. #ifdef DEBUG
  9148. nsCOMPtr<nsIDocShellTreeItem> parent;
  9149. GetSameTypeParent(getter_AddRefs(parent));
  9150. MOZ_ASSERT(!parent);
  9151. #endif
  9152. SetOrientationLock(eScreenOrientation_None);
  9153. if (mIsActive) {
  9154. ScreenOrientation::UpdateActiveOrientationLock(eScreenOrientation_None);
  9155. }
  9156. }
  9157. // Check for saving the presentation here, before calling Stop().
  9158. // This is necessary so that we can catch any pending requests.
  9159. // Since the new request has not been created yet, we pass null for the
  9160. // new request parameter.
  9161. // Also pass nullptr for the document, since it doesn't affect the return
  9162. // value for our purposes here.
  9163. bool savePresentation = CanSavePresentation(aLoadType, nullptr, nullptr);
  9164. // Don't stop current network activity for javascript: URL's since
  9165. // they might not result in any data, and thus nothing should be
  9166. // stopped in those cases. In the case where they do result in
  9167. // data, the javascript: URL channel takes care of stopping
  9168. // current network activity.
  9169. if (!isJavaScript && aFileName.IsVoid()) {
  9170. // Stop any current network activity.
  9171. // Also stop content if this is a zombie doc. otherwise
  9172. // the onload will be delayed by other loads initiated in the
  9173. // background by the first document that
  9174. // didn't fully load before the next load was initiated.
  9175. // If not a zombie, don't stop content until data
  9176. // starts arriving from the new URI...
  9177. nsCOMPtr<nsIContentViewer> zombieViewer;
  9178. if (mContentViewer) {
  9179. mContentViewer->GetPreviousViewer(getter_AddRefs(zombieViewer));
  9180. }
  9181. if (zombieViewer ||
  9182. LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_STOP_CONTENT)) {
  9183. rv = Stop(nsIWebNavigation::STOP_ALL);
  9184. } else {
  9185. rv = Stop(nsIWebNavigation::STOP_NETWORK);
  9186. }
  9187. if (NS_FAILED(rv)) {
  9188. return rv;
  9189. }
  9190. }
  9191. mLoadType = aLoadType;
  9192. // mLSHE should be assigned to aSHEntry, only after Stop() has
  9193. // been called. But when loading an error page, do not clear the
  9194. // mLSHE for the real page.
  9195. if (mLoadType != LOAD_ERROR_PAGE) {
  9196. SetHistoryEntry(&mLSHE, aSHEntry);
  9197. }
  9198. mSavingOldViewer = savePresentation;
  9199. // If we have a saved content viewer in history, restore and show it now.
  9200. if (aSHEntry && (mLoadType & LOAD_CMD_HISTORY)) {
  9201. // Make sure our history ID points to the same ID as
  9202. // SHEntry's docshell ID.
  9203. aSHEntry->GetDocshellID(&mHistoryID);
  9204. // It's possible that the previous viewer of mContentViewer is the
  9205. // viewer that will end up in aSHEntry when it gets closed. If that's
  9206. // the case, we need to go ahead and force it into its shentry so we
  9207. // can restore it.
  9208. if (mContentViewer) {
  9209. nsCOMPtr<nsIContentViewer> prevViewer;
  9210. mContentViewer->GetPreviousViewer(getter_AddRefs(prevViewer));
  9211. if (prevViewer) {
  9212. #ifdef DEBUG
  9213. nsCOMPtr<nsIContentViewer> prevPrevViewer;
  9214. prevViewer->GetPreviousViewer(getter_AddRefs(prevPrevViewer));
  9215. NS_ASSERTION(!prevPrevViewer, "Should never have viewer chain here");
  9216. #endif
  9217. nsCOMPtr<nsISHEntry> viewerEntry;
  9218. prevViewer->GetHistoryEntry(getter_AddRefs(viewerEntry));
  9219. if (viewerEntry == aSHEntry) {
  9220. // Make sure this viewer ends up in the right place
  9221. mContentViewer->SetPreviousViewer(nullptr);
  9222. prevViewer->Destroy();
  9223. }
  9224. }
  9225. }
  9226. nsCOMPtr<nsISHEntry> oldEntry = mOSHE;
  9227. bool restoring;
  9228. rv = RestorePresentation(aSHEntry, &restoring);
  9229. if (restoring) {
  9230. return rv;
  9231. }
  9232. // We failed to restore the presentation, so clean up.
  9233. // Both the old and new history entries could potentially be in
  9234. // an inconsistent state.
  9235. if (NS_FAILED(rv)) {
  9236. if (oldEntry) {
  9237. oldEntry->SyncPresentationState();
  9238. }
  9239. aSHEntry->SyncPresentationState();
  9240. }
  9241. }
  9242. nsAutoString srcdoc;
  9243. if (aFlags & INTERNAL_LOAD_FLAGS_IS_SRCDOC) {
  9244. srcdoc = aSrcdoc;
  9245. } else {
  9246. srcdoc = NullString();
  9247. }
  9248. net::PredictorLearn(aURI, nullptr,
  9249. nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, this);
  9250. net::PredictorPredict(aURI, nullptr,
  9251. nsINetworkPredictor::PREDICT_LOAD, this, nullptr);
  9252. nsCOMPtr<nsIRequest> req;
  9253. rv = DoURILoad(aURI, aOriginalURI, aLoadReplace,
  9254. aIsFromProcessingFrameAttributes, loadFromExternal,
  9255. (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI),
  9256. aReferrer,
  9257. !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
  9258. aReferrerPolicy,
  9259. aTriggeringPrincipal, principalToInherit, aTypeHint,
  9260. aFileName, aPostData, aHeadersData,
  9261. aFirstParty, aDocShell, getter_AddRefs(req),
  9262. (aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0,
  9263. (aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0,
  9264. (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0,
  9265. srcdoc, aBaseURI, contentType);
  9266. if (req && aRequest) {
  9267. NS_ADDREF(*aRequest = req);
  9268. }
  9269. if (NS_FAILED(rv)) {
  9270. nsCOMPtr<nsIChannel> chan(do_QueryInterface(req));
  9271. if (DisplayLoadError(rv, aURI, nullptr, chan) &&
  9272. (aFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
  9273. return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
  9274. }
  9275. }
  9276. return rv;
  9277. }
  9278. nsIPrincipal*
  9279. nsDocShell::GetInheritedPrincipal(bool aConsiderCurrentDocument)
  9280. {
  9281. nsCOMPtr<nsIDocument> document;
  9282. bool inheritedFromCurrent = false;
  9283. if (aConsiderCurrentDocument && mContentViewer) {
  9284. document = mContentViewer->GetDocument();
  9285. inheritedFromCurrent = true;
  9286. }
  9287. if (!document) {
  9288. nsCOMPtr<nsIDocShellTreeItem> parentItem;
  9289. GetSameTypeParent(getter_AddRefs(parentItem));
  9290. if (parentItem) {
  9291. document = parentItem->GetDocument();
  9292. }
  9293. }
  9294. if (!document) {
  9295. if (!aConsiderCurrentDocument) {
  9296. return nullptr;
  9297. }
  9298. // Make sure we end up with _something_ as the principal no matter
  9299. // what.If this fails, we'll just get a null docViewer and bail.
  9300. EnsureContentViewer();
  9301. if (!mContentViewer) {
  9302. return nullptr;
  9303. }
  9304. document = mContentViewer->GetDocument();
  9305. }
  9306. //-- Get the document's principal
  9307. if (document) {
  9308. nsIPrincipal* docPrincipal = document->NodePrincipal();
  9309. // Don't allow loads in typeContent docShells to inherit the system
  9310. // principal from existing documents.
  9311. if (inheritedFromCurrent &&
  9312. mItemType == typeContent &&
  9313. nsContentUtils::IsSystemPrincipal(docPrincipal)) {
  9314. return nullptr;
  9315. }
  9316. return docPrincipal;
  9317. }
  9318. return nullptr;
  9319. }
  9320. nsresult
  9321. nsDocShell::DoURILoad(nsIURI* aURI,
  9322. nsIURI* aOriginalURI,
  9323. bool aLoadReplace,
  9324. bool aIsFromProcessingFrameAttributes,
  9325. bool aLoadFromExternal,
  9326. bool aForceAllowDataURI,
  9327. nsIURI* aReferrerURI,
  9328. bool aSendReferrer,
  9329. uint32_t aReferrerPolicy,
  9330. nsIPrincipal* aTriggeringPrincipal,
  9331. nsIPrincipal* aPrincipalToInherit,
  9332. const char* aTypeHint,
  9333. const nsAString& aFileName,
  9334. nsIInputStream* aPostData,
  9335. nsIInputStream* aHeadersData,
  9336. bool aFirstParty,
  9337. nsIDocShell** aDocShell,
  9338. nsIRequest** aRequest,
  9339. bool aIsNewWindowTarget,
  9340. bool aBypassClassifier,
  9341. bool aForceAllowCookies,
  9342. const nsAString& aSrcdoc,
  9343. nsIURI* aBaseURI,
  9344. nsContentPolicyType aContentPolicyType)
  9345. {
  9346. // Double-check that we're still around to load this URI.
  9347. if (mIsBeingDestroyed) {
  9348. // Return NS_OK despite not doing anything to avoid throwing exceptions from
  9349. // nsLocation::SetHref if the unload handler of the existing page tears us
  9350. // down.
  9351. return NS_OK;
  9352. }
  9353. nsresult rv;
  9354. nsCOMPtr<nsIURILoader> uriLoader = do_GetService(NS_URI_LOADER_CONTRACTID, &rv);
  9355. if (NS_FAILED(rv)) {
  9356. return rv;
  9357. }
  9358. if (IsFrame()) {
  9359. MOZ_ASSERT(aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
  9360. aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME,
  9361. "DoURILoad thinks this is a frame and InternalLoad does not");
  9362. // Only allow view-source scheme in top-level docshells. view-source is
  9363. // the only scheme to which this applies at the moment due to potential
  9364. // timing attacks to read data from cross-origin iframes. If this widens
  9365. // we should add a protocol flag for whether the scheme is allowed in
  9366. // frames and use something like nsNetUtil::NS_URIChainHasFlags.
  9367. nsCOMPtr<nsIURI> tempURI = aURI;
  9368. nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
  9369. while (nestedURI) {
  9370. // view-source should always be an nsINestedURI, loop and check the
  9371. // scheme on this and all inner URIs that are also nested URIs.
  9372. bool isViewSource = false;
  9373. rv = tempURI->SchemeIs("view-source", &isViewSource);
  9374. if (NS_FAILED(rv) || isViewSource) {
  9375. return NS_ERROR_UNKNOWN_PROTOCOL;
  9376. }
  9377. nestedURI->GetInnerURI(getter_AddRefs(tempURI));
  9378. nestedURI = do_QueryInterface(tempURI);
  9379. }
  9380. } else {
  9381. MOZ_ASSERT(aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,
  9382. "DoURILoad thinks this is a document and InternalLoad does not");
  9383. }
  9384. // open a channel for the url
  9385. nsCOMPtr<nsIChannel> channel;
  9386. bool isSrcdoc = !aSrcdoc.IsVoid();
  9387. // There are two cases we care about:
  9388. // * Top-level load: In this case, loadingNode is null, but loadingWindow
  9389. // is our mScriptGlobal. We pass null for loadingPrincipal in this case.
  9390. // * Subframe load: loadingWindow is null, but loadingNode is the frame
  9391. // element for the load. loadingPrincipal is the NodePrincipal of the frame
  9392. // element.
  9393. nsCOMPtr<nsINode> loadingNode;
  9394. nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
  9395. nsCOMPtr<nsIPrincipal> loadingPrincipal;
  9396. nsCOMPtr<nsISupports> topLevelLoadingContext;
  9397. if (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
  9398. loadingNode = nullptr;
  9399. loadingPrincipal = nullptr;
  9400. loadingWindow = mScriptGlobal->AsOuter();
  9401. if (XRE_IsContentProcess()) {
  9402. // In e10s the child process doesn't have access to the element that
  9403. // contains the browsing context (because that element is in the chrome
  9404. // process).
  9405. nsCOMPtr<nsITabChild> tabChild = GetTabChild();
  9406. topLevelLoadingContext = ToSupports(tabChild);
  9407. } else {
  9408. // This is for loading non-e10s tabs and toplevel windows of various
  9409. // sorts.
  9410. // For the toplevel window cases, requestingElement will be null.
  9411. nsCOMPtr<Element> requestingElement =
  9412. loadingWindow->GetFrameElementInternal();
  9413. topLevelLoadingContext = requestingElement;
  9414. }
  9415. } else {
  9416. loadingWindow = nullptr;
  9417. loadingNode = mScriptGlobal->AsOuter()->GetFrameElementInternal();
  9418. if (loadingNode) {
  9419. // If we have a loading node, then use that as our loadingPrincipal.
  9420. loadingPrincipal = loadingNode->NodePrincipal();
  9421. #ifdef DEBUG
  9422. // Get the docshell type for requestingElement.
  9423. nsCOMPtr<nsIDocument> requestingDoc = loadingNode->OwnerDoc();
  9424. nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
  9425. // requestingElement docshell type = current docshell type.
  9426. MOZ_ASSERT(mItemType == elementDocShell->ItemType(),
  9427. "subframes should have the same docshell type as their parent");
  9428. #endif
  9429. } else {
  9430. // If this isn't a top-level load and mScriptGlobal's frame element is
  9431. // null, then the element got removed from the DOM while we were trying
  9432. // to load this resource. This docshell is scheduled for destruction
  9433. // already, so bail out here.
  9434. return NS_OK;
  9435. }
  9436. }
  9437. // Getting the right triggeringPrincipal needs to be updated and is only
  9438. // ready for use once bug 1182569 landed. Until then, we cannot rely on
  9439. // the triggeringPrincipal for TYPE_DOCUMENT loads.
  9440. MOZ_ASSERT(aTriggeringPrincipal, "Need a valid triggeringPrincipal");
  9441. bool isSandBoxed = mSandboxFlags & SANDBOXED_ORIGIN;
  9442. // only inherit if we have a aPrincipalToInherit
  9443. bool inherit = false;
  9444. if (aPrincipalToInherit) {
  9445. inherit = nsContentUtils::ChannelShouldInheritPrincipal(
  9446. aPrincipalToInherit,
  9447. aURI,
  9448. true, // aInheritForAboutBlank
  9449. isSrcdoc);
  9450. }
  9451. nsLoadFlags loadFlags = mDefaultLoadFlags;
  9452. nsSecurityFlags securityFlags =
  9453. nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
  9454. if (aFirstParty) {
  9455. // tag first party URL loads
  9456. loadFlags |= nsIChannel::LOAD_INITIAL_DOCUMENT_URI;
  9457. }
  9458. if (mLoadType == LOAD_ERROR_PAGE) {
  9459. // Error pages are LOAD_BACKGROUND
  9460. loadFlags |= nsIChannel::LOAD_BACKGROUND;
  9461. securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE;
  9462. }
  9463. if (inherit) {
  9464. securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
  9465. }
  9466. if (isSandBoxed) {
  9467. securityFlags |= nsILoadInfo::SEC_SANDBOXED;
  9468. }
  9469. RefPtr<LoadInfo> loadInfo =
  9470. (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) ?
  9471. new LoadInfo(loadingWindow, aTriggeringPrincipal, topLevelLoadingContext,
  9472. securityFlags) :
  9473. new LoadInfo(loadingPrincipal, aTriggeringPrincipal, loadingNode,
  9474. securityFlags, aContentPolicyType);
  9475. if (aPrincipalToInherit) {
  9476. loadInfo->SetPrincipalToInherit(aPrincipalToInherit);
  9477. }
  9478. loadInfo->SetLoadTriggeredFromExternal(aLoadFromExternal);
  9479. loadInfo->SetForceAllowDataURI(aForceAllowDataURI);
  9480. // We have to do this in case our OriginAttributes are different from the
  9481. // OriginAttributes of the parent document. Or in case there isn't a
  9482. // parent document.
  9483. NeckoOriginAttributes neckoAttrs;
  9484. bool isTopLevelDoc = aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT &&
  9485. mItemType == typeContent &&
  9486. !GetIsMozBrowserOrApp();
  9487. neckoAttrs.InheritFromDocShellToNecko(GetOriginAttributes(), isTopLevelDoc, aURI);
  9488. rv = loadInfo->SetOriginAttributes(neckoAttrs);
  9489. if (NS_WARN_IF(NS_FAILED(rv))) {
  9490. return rv;
  9491. }
  9492. if (aIsFromProcessingFrameAttributes) {
  9493. loadInfo->SetIsFromProcessingFrameAttributes();
  9494. }
  9495. if (!isSrcdoc) {
  9496. rv = NS_NewChannelInternal(getter_AddRefs(channel),
  9497. aURI,
  9498. loadInfo,
  9499. nullptr, // loadGroup
  9500. static_cast<nsIInterfaceRequestor*>(this),
  9501. loadFlags);
  9502. if (NS_FAILED(rv)) {
  9503. if (rv == NS_ERROR_UNKNOWN_PROTOCOL) {
  9504. // This is a uri with a protocol scheme we don't know how
  9505. // to handle. Embedders might still be interested in
  9506. // handling the load, though, so we fire a notification
  9507. // before throwing the load away.
  9508. bool abort = false;
  9509. nsresult rv2 = mContentListener->OnStartURIOpen(aURI, &abort);
  9510. if (NS_SUCCEEDED(rv2) && abort) {
  9511. // Hey, they're handling the load for us! How convenient!
  9512. return NS_OK;
  9513. }
  9514. }
  9515. return rv;
  9516. }
  9517. if (aBaseURI) {
  9518. nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
  9519. if (vsc) {
  9520. vsc->SetBaseURI(aBaseURI);
  9521. }
  9522. }
  9523. } else {
  9524. nsAutoCString scheme;
  9525. rv = aURI->GetScheme(scheme);
  9526. NS_ENSURE_SUCCESS(rv, rv);
  9527. bool isViewSource;
  9528. aURI->SchemeIs("view-source", &isViewSource);
  9529. if (isViewSource) {
  9530. nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
  9531. NS_ENSURE_TRUE(vsh, NS_ERROR_FAILURE);
  9532. rv = vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc,
  9533. loadInfo, getter_AddRefs(channel));
  9534. } else {
  9535. rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
  9536. aURI,
  9537. aSrcdoc,
  9538. NS_LITERAL_CSTRING("text/html"),
  9539. loadInfo,
  9540. true);
  9541. NS_ENSURE_SUCCESS(rv, rv);
  9542. nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
  9543. MOZ_ASSERT(isc);
  9544. isc->SetBaseURI(aBaseURI);
  9545. }
  9546. }
  9547. // Navigational requests that are same origin need to be upgraded in case
  9548. // upgrade-insecure-requests is present. Please note that in that case
  9549. // the triggeringPrincipal is holding the CSP that potentially
  9550. // holds upgrade-insecure-requests.
  9551. nsCOMPtr<nsIContentSecurityPolicy> csp;
  9552. aTriggeringPrincipal->GetCsp(getter_AddRefs(csp));
  9553. if (csp) {
  9554. bool upgradeInsecureRequests = false;
  9555. csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
  9556. if (upgradeInsecureRequests) {
  9557. // only upgrade if the navigation is same origin
  9558. nsCOMPtr<nsIPrincipal> resultPrincipal;
  9559. rv = nsContentUtils::GetSecurityManager()->
  9560. GetChannelResultPrincipal(channel,
  9561. getter_AddRefs(resultPrincipal));
  9562. NS_ENSURE_SUCCESS(rv, rv);
  9563. if (resultPrincipal->Equals(aTriggeringPrincipal)) {
  9564. static_cast<mozilla::LoadInfo*>(loadInfo.get())->SetUpgradeInsecureRequests();
  9565. }
  9566. }
  9567. }
  9568. nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
  9569. do_QueryInterface(channel);
  9570. if (appCacheChannel) {
  9571. // Any document load should not inherit application cache.
  9572. appCacheChannel->SetInheritApplicationCache(false);
  9573. // Loads with the correct permissions should check for a matching
  9574. // application cache.
  9575. if (GeckoProcessType_Default != XRE_GetProcessType()) {
  9576. // Permission will be checked in the parent process
  9577. appCacheChannel->SetChooseApplicationCache(true);
  9578. } else {
  9579. nsCOMPtr<nsIScriptSecurityManager> secMan =
  9580. do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
  9581. if (secMan) {
  9582. nsCOMPtr<nsIPrincipal> principal;
  9583. secMan->GetDocShellCodebasePrincipal(aURI, this,
  9584. getter_AddRefs(principal));
  9585. appCacheChannel->SetChooseApplicationCache(
  9586. NS_ShouldCheckAppCache(principal, UsePrivateBrowsing()));
  9587. }
  9588. }
  9589. }
  9590. // Make sure to give the caller a channel if we managed to create one
  9591. // This is important for correct error page/session history interaction
  9592. if (aRequest) {
  9593. NS_ADDREF(*aRequest = channel);
  9594. }
  9595. if (aOriginalURI) {
  9596. channel->SetOriginalURI(aOriginalURI);
  9597. if (aLoadReplace) {
  9598. uint32_t loadFlags;
  9599. channel->GetLoadFlags(&loadFlags);
  9600. NS_ENSURE_SUCCESS(rv, rv);
  9601. channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
  9602. }
  9603. } else {
  9604. channel->SetOriginalURI(aURI);
  9605. }
  9606. if (aTypeHint && *aTypeHint) {
  9607. channel->SetContentType(nsDependentCString(aTypeHint));
  9608. mContentTypeHint = aTypeHint;
  9609. } else {
  9610. mContentTypeHint.Truncate();
  9611. }
  9612. if (!aFileName.IsVoid()) {
  9613. rv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
  9614. NS_ENSURE_SUCCESS(rv, rv);
  9615. if (!aFileName.IsEmpty()) {
  9616. rv = channel->SetContentDispositionFilename(aFileName);
  9617. NS_ENSURE_SUCCESS(rv, rv);
  9618. }
  9619. }
  9620. if (mLoadType == LOAD_NORMAL_ALLOW_MIXED_CONTENT ||
  9621. mLoadType == LOAD_RELOAD_ALLOW_MIXED_CONTENT) {
  9622. rv = SetMixedContentChannel(channel);
  9623. NS_ENSURE_SUCCESS(rv, rv);
  9624. } else if (mMixedContentChannel) {
  9625. /*
  9626. * If the user "Disables Protection on This Page", we call
  9627. * SetMixedContentChannel for the first time, otherwise
  9628. * mMixedContentChannel is still null.
  9629. * Later, if the new channel passes a same orign check, we remember the
  9630. * users decision by calling SetMixedContentChannel using the new channel.
  9631. * This way, the user does not have to click the disable protection button
  9632. * over and over for browsing the same site.
  9633. */
  9634. rv = nsContentUtils::CheckSameOrigin(mMixedContentChannel, channel);
  9635. if (NS_FAILED(rv) || NS_FAILED(SetMixedContentChannel(channel))) {
  9636. SetMixedContentChannel(nullptr);
  9637. }
  9638. }
  9639. // hack
  9640. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
  9641. nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
  9642. do_QueryInterface(channel));
  9643. if (httpChannelInternal) {
  9644. if (aForceAllowCookies) {
  9645. httpChannelInternal->SetThirdPartyFlags(
  9646. nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
  9647. }
  9648. if (aFirstParty) {
  9649. httpChannelInternal->SetDocumentURI(aURI);
  9650. } else {
  9651. httpChannelInternal->SetDocumentURI(aReferrerURI);
  9652. }
  9653. httpChannelInternal->SetRedirectMode(
  9654. nsIHttpChannelInternal::REDIRECT_MODE_MANUAL);
  9655. }
  9656. nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(channel));
  9657. if (props) {
  9658. // save true referrer for those who need it (e.g. xpinstall whitelisting)
  9659. // Currently only http and ftp channels support this.
  9660. props->SetPropertyAsInterface(NS_LITERAL_STRING("docshell.internalReferrer"),
  9661. aReferrerURI);
  9662. }
  9663. nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel));
  9664. /* Get the cache Key from SH */
  9665. nsCOMPtr<nsISupports> cacheKey;
  9666. if (cacheChannel) {
  9667. if (mLSHE) {
  9668. mLSHE->GetCacheKey(getter_AddRefs(cacheKey));
  9669. } else if (mOSHE) { // for reload cases
  9670. mOSHE->GetCacheKey(getter_AddRefs(cacheKey));
  9671. }
  9672. }
  9673. // figure out if we need to set the post data stream on the channel...
  9674. if (aPostData) {
  9675. nsCOMPtr<nsIFormPOSTActionChannel> postChannel(do_QueryInterface(channel));
  9676. if (postChannel) {
  9677. // XXX it's a bit of a hack to rewind the postdata stream here but
  9678. // it has to be done in case the post data is being reused multiple
  9679. // times.
  9680. nsCOMPtr<nsISeekableStream> postDataSeekable =
  9681. do_QueryInterface(aPostData);
  9682. if (postDataSeekable) {
  9683. rv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
  9684. NS_ENSURE_SUCCESS(rv, rv);
  9685. }
  9686. // we really need to have a content type associated with this stream!!
  9687. postChannel->SetUploadStream(aPostData, EmptyCString(), -1);
  9688. }
  9689. /* If there is a valid postdata *and* it is a History Load,
  9690. * set up the cache key on the channel, to retrieve the
  9691. * data *only* from the cache. If it is a normal reload, the
  9692. * cache is free to go to the server for updated postdata.
  9693. */
  9694. if (cacheChannel && cacheKey) {
  9695. if (mLoadType == LOAD_HISTORY ||
  9696. mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
  9697. cacheChannel->SetCacheKey(cacheKey);
  9698. uint32_t loadFlags;
  9699. if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))) {
  9700. channel->SetLoadFlags(
  9701. loadFlags | nsICachingChannel::LOAD_ONLY_FROM_CACHE);
  9702. }
  9703. } else if (mLoadType == LOAD_RELOAD_NORMAL) {
  9704. cacheChannel->SetCacheKey(cacheKey);
  9705. }
  9706. }
  9707. } else {
  9708. /* If there is no postdata, set the cache key on the channel, and
  9709. * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel
  9710. * will be free to get it from net if it is not found in cache.
  9711. * New cache may use it creatively on CGI pages with GET
  9712. * method and even on those that say "no-cache"
  9713. */
  9714. if (mLoadType == LOAD_HISTORY ||
  9715. mLoadType == LOAD_RELOAD_NORMAL ||
  9716. mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
  9717. if (cacheChannel && cacheKey) {
  9718. cacheChannel->SetCacheKey(cacheKey);
  9719. }
  9720. }
  9721. }
  9722. if (httpChannel) {
  9723. if (aHeadersData) {
  9724. rv = AddHeadersToChannel(aHeadersData, httpChannel);
  9725. }
  9726. // Set the referrer explicitly
  9727. if (aReferrerURI && aSendReferrer) {
  9728. // Referrer is currenly only set for link clicks here.
  9729. httpChannel->SetReferrerWithPolicy(aReferrerURI, aReferrerPolicy);
  9730. }
  9731. // set Content-Signature enforcing bit if aOriginalURI == about:newtab
  9732. if (aOriginalURI && httpChannel) {
  9733. if (IsAboutNewtab(aOriginalURI)) {
  9734. nsCOMPtr<nsILoadInfo> loadInfo = httpChannel->GetLoadInfo();
  9735. if (loadInfo) {
  9736. loadInfo->SetVerifySignedContent(true);
  9737. }
  9738. }
  9739. }
  9740. }
  9741. nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel);
  9742. if (scriptChannel) {
  9743. // Allow execution against our context if the principals match
  9744. scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
  9745. }
  9746. if (aIsNewWindowTarget) {
  9747. nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel);
  9748. if (props) {
  9749. props->SetPropertyAsBool(NS_LITERAL_STRING("docshell.newWindowTarget"),
  9750. true);
  9751. }
  9752. }
  9753. nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(channel));
  9754. if (timedChannel) {
  9755. timedChannel->SetTimingEnabled(true);
  9756. nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
  9757. if (IsFrame() && win) {
  9758. nsCOMPtr<Element> frameElement = win->GetFrameElementInternal();
  9759. if (frameElement) {
  9760. timedChannel->SetInitiatorType(frameElement->LocalName());
  9761. }
  9762. }
  9763. }
  9764. rv = DoChannelLoad(channel, uriLoader, aBypassClassifier);
  9765. //
  9766. // If the channel load failed, we failed and nsIWebProgress just ain't
  9767. // gonna happen.
  9768. //
  9769. if (NS_SUCCEEDED(rv)) {
  9770. if (aDocShell) {
  9771. *aDocShell = this;
  9772. NS_ADDREF(*aDocShell);
  9773. }
  9774. }
  9775. return rv;
  9776. }
  9777. static nsresult
  9778. AppendSegmentToString(nsIInputStream* aIn,
  9779. void* aClosure,
  9780. const char* aFromRawSegment,
  9781. uint32_t aToOffset,
  9782. uint32_t aCount,
  9783. uint32_t* aWriteCount)
  9784. {
  9785. // aFromSegment now contains aCount bytes of data.
  9786. nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure);
  9787. buf->Append(aFromRawSegment, aCount);
  9788. // Indicate that we have consumed all of aFromSegment
  9789. *aWriteCount = aCount;
  9790. return NS_OK;
  9791. }
  9792. nsresult
  9793. nsDocShell::AddHeadersToChannel(nsIInputStream* aHeadersData,
  9794. nsIChannel* aGenericChannel)
  9795. {
  9796. nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel);
  9797. NS_ENSURE_STATE(httpChannel);
  9798. uint32_t numRead;
  9799. nsAutoCString headersString;
  9800. nsresult rv = aHeadersData->ReadSegments(AppendSegmentToString,
  9801. &headersString,
  9802. UINT32_MAX,
  9803. &numRead);
  9804. NS_ENSURE_SUCCESS(rv, rv);
  9805. // used during the manipulation of the String from the InputStream
  9806. nsAutoCString headerName;
  9807. nsAutoCString headerValue;
  9808. int32_t crlf;
  9809. int32_t colon;
  9810. //
  9811. // Iterate over the headersString: for each "\r\n" delimited chunk,
  9812. // add the value as a header to the nsIHttpChannel
  9813. //
  9814. static const char kWhitespace[] = "\b\t\r\n ";
  9815. while (true) {
  9816. crlf = headersString.Find("\r\n");
  9817. if (crlf == kNotFound) {
  9818. return NS_OK;
  9819. }
  9820. const nsCSubstring& oneHeader = StringHead(headersString, crlf);
  9821. colon = oneHeader.FindChar(':');
  9822. if (colon == kNotFound) {
  9823. return NS_ERROR_UNEXPECTED;
  9824. }
  9825. headerName = StringHead(oneHeader, colon);
  9826. headerValue = Substring(oneHeader, colon + 1);
  9827. headerName.Trim(kWhitespace);
  9828. headerValue.Trim(kWhitespace);
  9829. headersString.Cut(0, crlf + 2);
  9830. //
  9831. // FINALLY: we can set the header!
  9832. //
  9833. rv = httpChannel->SetRequestHeader(headerName, headerValue, true);
  9834. NS_ENSURE_SUCCESS(rv, rv);
  9835. }
  9836. NS_NOTREACHED("oops");
  9837. return NS_ERROR_UNEXPECTED;
  9838. }
  9839. nsresult
  9840. nsDocShell::DoChannelLoad(nsIChannel* aChannel,
  9841. nsIURILoader* aURILoader,
  9842. bool aBypassClassifier)
  9843. {
  9844. nsresult rv;
  9845. // Mark the channel as being a document URI and allow content sniffing...
  9846. nsLoadFlags loadFlags = 0;
  9847. (void)aChannel->GetLoadFlags(&loadFlags);
  9848. loadFlags |= nsIChannel::LOAD_DOCUMENT_URI |
  9849. nsIChannel::LOAD_CALL_CONTENT_SNIFFERS;
  9850. // Load attributes depend on load type...
  9851. switch (mLoadType) {
  9852. case LOAD_HISTORY: {
  9853. // Only send VALIDATE_NEVER if mLSHE's URI was never changed via
  9854. // push/replaceState (bug 669671).
  9855. bool uriModified = false;
  9856. if (mLSHE) {
  9857. mLSHE->GetURIWasModified(&uriModified);
  9858. }
  9859. if (!uriModified) {
  9860. loadFlags |= nsIRequest::VALIDATE_NEVER;
  9861. }
  9862. break;
  9863. }
  9864. case LOAD_RELOAD_CHARSET_CHANGE: {
  9865. // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we only want
  9866. // to force cache load for this channel, not the whole loadGroup.
  9867. nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(aChannel);
  9868. if (cachingChannel) {
  9869. cachingChannel->SetAllowStaleCacheContent(true);
  9870. }
  9871. break;
  9872. }
  9873. case LOAD_RELOAD_NORMAL:
  9874. case LOAD_REFRESH:
  9875. loadFlags |= nsIRequest::VALIDATE_ALWAYS;
  9876. break;
  9877. case LOAD_NORMAL_BYPASS_CACHE:
  9878. case LOAD_NORMAL_BYPASS_PROXY:
  9879. case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
  9880. case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
  9881. case LOAD_RELOAD_BYPASS_CACHE:
  9882. case LOAD_RELOAD_BYPASS_PROXY:
  9883. case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
  9884. case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
  9885. case LOAD_REPLACE_BYPASS_CACHE:
  9886. loadFlags |= nsIRequest::LOAD_BYPASS_CACHE |
  9887. nsIRequest::LOAD_FRESH_CONNECTION;
  9888. break;
  9889. case LOAD_NORMAL:
  9890. case LOAD_LINK:
  9891. // Set cache checking flags
  9892. switch (Preferences::GetInt("browser.cache.check_doc_frequency", -1)) {
  9893. case 0:
  9894. loadFlags |= nsIRequest::VALIDATE_ONCE_PER_SESSION;
  9895. break;
  9896. case 1:
  9897. loadFlags |= nsIRequest::VALIDATE_ALWAYS;
  9898. break;
  9899. case 2:
  9900. loadFlags |= nsIRequest::VALIDATE_NEVER;
  9901. break;
  9902. }
  9903. break;
  9904. }
  9905. if (!aBypassClassifier) {
  9906. loadFlags |= nsIChannel::LOAD_CLASSIFY_URI;
  9907. }
  9908. // If the user pressed shift-reload, then do not allow ServiceWorker
  9909. // interception to occur. See step 12.1 of the SW HandleFetch algorithm.
  9910. if (IsForceReloadType(mLoadType)) {
  9911. loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
  9912. }
  9913. (void)aChannel->SetLoadFlags(loadFlags);
  9914. uint32_t openFlags = 0;
  9915. if (mLoadType == LOAD_LINK) {
  9916. openFlags |= nsIURILoader::IS_CONTENT_PREFERRED;
  9917. }
  9918. if (!mAllowContentRetargeting) {
  9919. openFlags |= nsIURILoader::DONT_RETARGET;
  9920. }
  9921. rv = aURILoader->OpenURI(aChannel, openFlags, this);
  9922. NS_ENSURE_SUCCESS(rv, rv);
  9923. return NS_OK;
  9924. }
  9925. nsresult
  9926. nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
  9927. nsACString& aNewHash, uint32_t aLoadType)
  9928. {
  9929. if (!mCurrentURI) {
  9930. return NS_OK;
  9931. }
  9932. nsCOMPtr<nsIPresShell> shell = GetPresShell();
  9933. if (!shell) {
  9934. // If we failed to get the shell, or if there is no shell,
  9935. // nothing left to do here.
  9936. return NS_OK;
  9937. }
  9938. nsIScrollableFrame* rootScroll = shell->GetRootScrollFrameAsScrollable();
  9939. if (rootScroll) {
  9940. rootScroll->ClearDidHistoryRestore();
  9941. }
  9942. // If we have no new anchor, we do not want to scroll, unless there is a
  9943. // current anchor and we are doing a history load. So return if we have no
  9944. // new anchor, and there is no current anchor or the load is not a history
  9945. // load.
  9946. if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef) {
  9947. return NS_OK;
  9948. }
  9949. // Both the new and current URIs refer to the same page. We can now
  9950. // browse to the hash stored in the new URI.
  9951. if (!aNewHash.IsEmpty()) {
  9952. // anchor is there, but if it's a load from history,
  9953. // we don't have any anchor jumping to do
  9954. bool scroll = aLoadType != LOAD_HISTORY &&
  9955. aLoadType != LOAD_RELOAD_NORMAL;
  9956. char* str = ToNewCString(aNewHash);
  9957. if (!str) {
  9958. return NS_ERROR_OUT_OF_MEMORY;
  9959. }
  9960. // nsUnescape modifies the string that is passed into it.
  9961. nsUnescape(str);
  9962. // We assume that the bytes are in UTF-8, as it says in the
  9963. // spec:
  9964. // http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.1
  9965. // We try the UTF-8 string first, and then try the document's
  9966. // charset (see below). If the string is not UTF-8,
  9967. // conversion will fail and give us an empty Unicode string.
  9968. // In that case, we should just fall through to using the
  9969. // page's charset.
  9970. nsresult rv = NS_ERROR_FAILURE;
  9971. NS_ConvertUTF8toUTF16 uStr(str);
  9972. if (!uStr.IsEmpty()) {
  9973. rv = shell->GoToAnchor(NS_ConvertUTF8toUTF16(str), scroll,
  9974. nsIPresShell::SCROLL_SMOOTH_AUTO);
  9975. }
  9976. free(str);
  9977. // Above will fail if the anchor name is not UTF-8. Need to
  9978. // convert from document charset to unicode.
  9979. if (NS_FAILED(rv)) {
  9980. // Get a document charset
  9981. NS_ENSURE_TRUE(mContentViewer, NS_ERROR_FAILURE);
  9982. nsIDocument* doc = mContentViewer->GetDocument();
  9983. NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
  9984. const nsACString& aCharset = doc->GetDocumentCharacterSet();
  9985. nsCOMPtr<nsITextToSubURI> textToSubURI =
  9986. do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
  9987. NS_ENSURE_SUCCESS(rv, rv);
  9988. // Unescape and convert to unicode
  9989. nsXPIDLString uStr;
  9990. rv = textToSubURI->UnEscapeAndConvert(PromiseFlatCString(aCharset).get(),
  9991. PromiseFlatCString(aNewHash).get(),
  9992. getter_Copies(uStr));
  9993. NS_ENSURE_SUCCESS(rv, rv);
  9994. // Ignore return value of GoToAnchor, since it will return an error
  9995. // if there is no such anchor in the document, which is actually a
  9996. // success condition for us (we want to update the session history
  9997. // with the new URI no matter whether we actually scrolled
  9998. // somewhere).
  9999. //
  10000. // When aNewHash contains "%00", unescaped string may be empty.
  10001. // And GoToAnchor asserts if we ask it to scroll to an empty ref.
  10002. shell->GoToAnchor(uStr, scroll && !uStr.IsEmpty(),
  10003. nsIPresShell::SCROLL_SMOOTH_AUTO);
  10004. }
  10005. } else {
  10006. // Tell the shell it's at an anchor, without scrolling.
  10007. shell->GoToAnchor(EmptyString(), false);
  10008. // An empty anchor was found, but if it's a load from history,
  10009. // we don't have to jump to the top of the page. Scrollbar
  10010. // position will be restored by the caller, based on positions
  10011. // stored in session history.
  10012. if (aLoadType == LOAD_HISTORY || aLoadType == LOAD_RELOAD_NORMAL) {
  10013. return NS_OK;
  10014. }
  10015. // An empty anchor. Scroll to the top of the page. Ignore the
  10016. // return value; failure to scroll here (e.g. if there is no
  10017. // root scrollframe) is not grounds for canceling the load!
  10018. SetCurScrollPosEx(0, 0);
  10019. }
  10020. return NS_OK;
  10021. }
  10022. void
  10023. nsDocShell::SetupReferrerFromChannel(nsIChannel* aChannel)
  10024. {
  10025. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
  10026. if (httpChannel) {
  10027. nsCOMPtr<nsIURI> referrer;
  10028. nsresult rv = httpChannel->GetReferrer(getter_AddRefs(referrer));
  10029. if (NS_SUCCEEDED(rv)) {
  10030. SetReferrerURI(referrer);
  10031. }
  10032. uint32_t referrerPolicy;
  10033. rv = httpChannel->GetReferrerPolicy(&referrerPolicy);
  10034. if (NS_SUCCEEDED(rv)) {
  10035. SetReferrerPolicy(referrerPolicy);
  10036. }
  10037. }
  10038. }
  10039. bool
  10040. nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
  10041. nsIPrincipal* aTriggeringPrincipal,
  10042. nsIPrincipal* aPrincipalToInherit,
  10043. uint32_t aLoadType, bool aFireOnLocationChange,
  10044. bool aAddToGlobalHistory, bool aCloneSHChildren)
  10045. {
  10046. NS_PRECONDITION(aURI, "uri is null");
  10047. NS_PRECONDITION(!aChannel || !aTriggeringPrincipal, "Shouldn't have both set");
  10048. MOZ_ASSERT(!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal));
  10049. #if defined(DEBUG)
  10050. if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)) {
  10051. nsAutoCString chanName;
  10052. if (aChannel) {
  10053. aChannel->GetName(chanName);
  10054. } else {
  10055. chanName.AssignLiteral("<no channel>");
  10056. }
  10057. MOZ_LOG(gDocShellLog, LogLevel::Debug,
  10058. ("nsDocShell[%p]::OnNewURI(\"%s\", [%s], 0x%x)\n",
  10059. this, aURI->GetSpecOrDefault().get(), chanName.get(), aLoadType));
  10060. }
  10061. #endif
  10062. bool equalUri = false;
  10063. // Get the post data and the HTTP response code from the channel.
  10064. uint32_t responseStatus = 0;
  10065. nsCOMPtr<nsIInputStream> inputStream;
  10066. if (aChannel) {
  10067. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
  10068. // Check if the HTTPChannel is hiding under a multiPartChannel
  10069. if (!httpChannel) {
  10070. GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
  10071. }
  10072. if (httpChannel) {
  10073. nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
  10074. if (uploadChannel) {
  10075. uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
  10076. }
  10077. // If the response status indicates an error, unlink this session
  10078. // history entry from any entries sharing its document.
  10079. nsresult rv = httpChannel->GetResponseStatus(&responseStatus);
  10080. if (mLSHE && NS_SUCCEEDED(rv) && responseStatus >= 400) {
  10081. mLSHE->AbandonBFCacheEntry();
  10082. }
  10083. }
  10084. }
  10085. // Determine if this type of load should update history.
  10086. bool updateGHistory = !(aLoadType == LOAD_BYPASS_HISTORY ||
  10087. aLoadType == LOAD_ERROR_PAGE ||
  10088. aLoadType & LOAD_CMD_HISTORY);
  10089. // We don't update session history on reload unless we're loading
  10090. // an iframe in shift-reload case.
  10091. bool updateSHistory = updateGHistory &&
  10092. (!(aLoadType & LOAD_CMD_RELOAD) ||
  10093. (IsForceReloadType(aLoadType) && IsFrame()));
  10094. // Create SH Entry (mLSHE) only if there is a SessionHistory object in the
  10095. // current frame or in the root docshell.
  10096. nsCOMPtr<nsISHistory> rootSH = mSessionHistory;
  10097. if (!rootSH) {
  10098. // Get the handle to SH from the root docshell
  10099. GetRootSessionHistory(getter_AddRefs(rootSH));
  10100. if (!rootSH) {
  10101. updateSHistory = false;
  10102. updateGHistory = false; // XXX Why global history too?
  10103. }
  10104. }
  10105. // Check if the url to be loaded is the same as the one already loaded.
  10106. if (mCurrentURI) {
  10107. aURI->Equals(mCurrentURI, &equalUri);
  10108. }
  10109. #ifdef DEBUG
  10110. bool shAvailable = (rootSH != nullptr);
  10111. // XXX This log message is almost useless because |updateSHistory|
  10112. // and |updateGHistory| are not correct at this point.
  10113. MOZ_LOG(gDocShellLog, LogLevel::Debug,
  10114. (" shAvailable=%i updateSHistory=%i updateGHistory=%i"
  10115. " equalURI=%i\n",
  10116. shAvailable, updateSHistory, updateGHistory, equalUri));
  10117. if (shAvailable && mCurrentURI && !mOSHE && aLoadType != LOAD_ERROR_PAGE) {
  10118. NS_ASSERTION(NS_IsAboutBlank(mCurrentURI),
  10119. "no SHEntry for a non-transient viewer?");
  10120. }
  10121. #endif
  10122. /* If the url to be loaded is the same as the one already there,
  10123. * and the original loadType is LOAD_NORMAL, LOAD_LINK, or
  10124. * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that
  10125. * AddToSessionHistory() won't mess with the current SHEntry and
  10126. * if this page has any frame children, it also will be handled
  10127. * properly. see bug 83684
  10128. *
  10129. * NB: If mOSHE is null but we have a current URI, then it means
  10130. * that we must be at the transient about:blank content viewer
  10131. * (asserted above) and we should let the normal load continue,
  10132. * since there's nothing to replace.
  10133. *
  10134. * XXX Hopefully changing the loadType at this time will not hurt
  10135. * anywhere. The other way to take care of sequentially repeating
  10136. * frameset pages is to add new methods to nsIDocShellTreeItem.
  10137. * Hopefully I don't have to do that.
  10138. */
  10139. if (equalUri &&
  10140. mOSHE &&
  10141. (mLoadType == LOAD_NORMAL ||
  10142. mLoadType == LOAD_LINK ||
  10143. mLoadType == LOAD_STOP_CONTENT) &&
  10144. !inputStream) {
  10145. mLoadType = LOAD_NORMAL_REPLACE;
  10146. }
  10147. // If this is a refresh to the currently loaded url, we don't
  10148. // have to update session or global history.
  10149. if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) {
  10150. SetHistoryEntry(&mLSHE, mOSHE);
  10151. }
  10152. /* If the user pressed shift-reload, cache will create a new cache key
  10153. * for the page. Save the new cacheKey in Session History.
  10154. * see bug 90098
  10155. */
  10156. if (aChannel && IsForceReloadType(aLoadType)) {
  10157. MOZ_ASSERT(!updateSHistory || IsFrame(),
  10158. "We shouldn't be updating session history for forced"
  10159. " reloads unless we're in a newly created iframe!");
  10160. nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel));
  10161. nsCOMPtr<nsISupports> cacheKey;
  10162. // Get the Cache Key and store it in SH.
  10163. if (cacheChannel) {
  10164. cacheChannel->GetCacheKey(getter_AddRefs(cacheKey));
  10165. }
  10166. // If we already have a loading history entry, store the new cache key
  10167. // in it. Otherwise, since we're doing a reload and won't be updating
  10168. // our history entry, store the cache key in our current history entry.
  10169. if (mLSHE) {
  10170. mLSHE->SetCacheKey(cacheKey);
  10171. } else if (mOSHE) {
  10172. mOSHE->SetCacheKey(cacheKey);
  10173. }
  10174. // Since we're force-reloading, clear all the sub frame history.
  10175. ClearFrameHistory(mLSHE);
  10176. ClearFrameHistory(mOSHE);
  10177. }
  10178. if (aLoadType == LOAD_RELOAD_NORMAL) {
  10179. nsCOMPtr<nsISHEntry> currentSH;
  10180. bool oshe = false;
  10181. GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
  10182. bool dynamicallyAddedChild = false;
  10183. if (currentSH) {
  10184. currentSH->HasDynamicallyAddedChild(&dynamicallyAddedChild);
  10185. }
  10186. if (dynamicallyAddedChild) {
  10187. ClearFrameHistory(currentSH);
  10188. }
  10189. }
  10190. if (aLoadType == LOAD_REFRESH) {
  10191. ClearFrameHistory(mLSHE);
  10192. ClearFrameHistory(mOSHE);
  10193. }
  10194. if (updateSHistory) {
  10195. // Update session history if necessary...
  10196. if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) {
  10197. /* This is a fresh page getting loaded for the first time
  10198. *.Create a Entry for it and add it to SH, if this is the
  10199. * rootDocShell
  10200. */
  10201. (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal,
  10202. aPrincipalToInherit, aCloneSHChildren,
  10203. getter_AddRefs(mLSHE));
  10204. }
  10205. } else if (mSessionHistory && mLSHE && mURIResultedInDocument) {
  10206. // Even if we don't add anything to SHistory, ensure the current index
  10207. // points to the same SHEntry as our mLSHE.
  10208. int32_t index = 0;
  10209. mSessionHistory->GetRequestedIndex(&index);
  10210. if (index == -1) {
  10211. mSessionHistory->GetIndex(&index);
  10212. }
  10213. nsCOMPtr<nsISHEntry> currentSH;
  10214. mSessionHistory->GetEntryAtIndex(index, false, getter_AddRefs(currentSH));
  10215. if (currentSH != mLSHE) {
  10216. nsCOMPtr<nsISHistoryInternal> shPrivate =
  10217. do_QueryInterface(mSessionHistory);
  10218. shPrivate->ReplaceEntry(index, mLSHE);
  10219. }
  10220. }
  10221. // If this is a POST request, we do not want to include this in global
  10222. // history.
  10223. if (updateGHistory && aAddToGlobalHistory && !ChannelIsPost(aChannel)) {
  10224. nsCOMPtr<nsIURI> previousURI;
  10225. uint32_t previousFlags = 0;
  10226. if (aLoadType & LOAD_CMD_RELOAD) {
  10227. // On a reload request, we don't set redirecting flags.
  10228. previousURI = aURI;
  10229. } else {
  10230. ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags);
  10231. }
  10232. // Note: We don't use |referrer| when our global history is
  10233. // based on IHistory.
  10234. nsCOMPtr<nsIURI> referrer;
  10235. // Treat referrer as null if there is an error getting it.
  10236. (void)NS_GetReferrerFromChannel(aChannel, getter_AddRefs(referrer));
  10237. AddURIVisit(aURI, referrer, previousURI, previousFlags, responseStatus);
  10238. }
  10239. // If this was a history load or a refresh, or it was a history load but
  10240. // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index
  10241. // in session history.
  10242. if (rootSH &&
  10243. ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) ||
  10244. mLoadType == LOAD_NORMAL_REPLACE)) {
  10245. nsCOMPtr<nsISHistoryInternal> shInternal(do_QueryInterface(rootSH));
  10246. if (shInternal) {
  10247. rootSH->GetIndex(&mPreviousTransIndex);
  10248. shInternal->UpdateIndex();
  10249. rootSH->GetIndex(&mLoadedTransIndex);
  10250. #ifdef DEBUG_PAGE_CACHE
  10251. printf("Previous index: %d, Loaded index: %d\n\n",
  10252. mPreviousTransIndex, mLoadedTransIndex);
  10253. #endif
  10254. }
  10255. }
  10256. // aCloneSHChildren exactly means "we are not loading a new document".
  10257. uint32_t locationFlags =
  10258. aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0;
  10259. bool onLocationChangeNeeded = SetCurrentURI(aURI, aChannel,
  10260. aFireOnLocationChange,
  10261. locationFlags);
  10262. // Make sure to store the referrer from the channel, if any
  10263. SetupReferrerFromChannel(aChannel);
  10264. return onLocationChangeNeeded;
  10265. }
  10266. bool
  10267. nsDocShell::OnLoadingSite(nsIChannel* aChannel, bool aFireOnLocationChange,
  10268. bool aAddToGlobalHistory)
  10269. {
  10270. nsCOMPtr<nsIURI> uri;
  10271. // If this a redirect, use the final url (uri)
  10272. // else use the original url
  10273. //
  10274. // Note that this should match what documents do (see nsDocument::Reset).
  10275. NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
  10276. NS_ENSURE_TRUE(uri, false);
  10277. // Pass false for aCloneSHChildren, since we're loading a new page here.
  10278. return OnNewURI(uri, aChannel, nullptr, nullptr, mLoadType, aFireOnLocationChange,
  10279. aAddToGlobalHistory, false);
  10280. }
  10281. void
  10282. nsDocShell::SetReferrerURI(nsIURI* aURI)
  10283. {
  10284. mReferrerURI = aURI; // This assigment addrefs
  10285. }
  10286. void
  10287. nsDocShell::SetReferrerPolicy(uint32_t aReferrerPolicy)
  10288. {
  10289. mReferrerPolicy = aReferrerPolicy;
  10290. }
  10291. //*****************************************************************************
  10292. // nsDocShell: Session History
  10293. //*****************************************************************************
  10294. bool
  10295. nsDocShell::IsStateChangeFlooding()
  10296. {
  10297. // Issue #1688: Let's copy Firefox's strategy for state flooding here, so
  10298. // that our implementations are interoperable.
  10299. if (mStateFloodGuardCount > kStateUpdateLimit) {
  10300. TimeStamp now = TimeStamp::Now();
  10301. if (now - mStateFloodGuardUpdated > TimeDuration::FromSeconds(kRefreshTimeSecs)) {
  10302. mStateFloodGuardCount = 0;
  10303. mStateFloodGuardUpdated = now;
  10304. mStateFloodGuardReported = false;
  10305. return false;
  10306. }
  10307. return true;
  10308. }
  10309. mStateFloodGuardCount++;
  10310. return false;
  10311. }
  10312. NS_IMETHODIMP
  10313. nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
  10314. const nsAString& aURL, bool aReplace, JSContext* aCx)
  10315. {
  10316. // Implements History.pushState and History.replaceState
  10317. // Here's what we do, roughly in the order specified by HTML5. The specific
  10318. // steps we are executing are at
  10319. // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate>
  10320. // and
  10321. // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>.
  10322. // This function basically implements #dom-history-pushstate and
  10323. // UpdateURLAndHistory implements #url-and-history-update-steps.
  10324. //
  10325. // A. Serialize aData using structured clone. This is #dom-history-pushstate
  10326. // step 5.
  10327. // B. If the third argument is present, #dom-history-pushstate step 7.
  10328. // 7.1. Resolve the url, relative to our document.
  10329. // 7.2. If (a) fails, raise a SECURITY_ERR
  10330. // 7.4. Compare the resulting absolute URL to the document's address. If
  10331. // any part of the URLs difer other than the <path>, <query>, and
  10332. // <fragment> components, raise a SECURITY_ERR and abort.
  10333. // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3:
  10334. // Remove from the session history all entries after the current entry,
  10335. // as we would after a regular navigation, and save the current
  10336. // entry's scroll position (bug 590573).
  10337. // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate,
  10338. // either add a state object entry to the session history after the
  10339. // current entry with the following properties, or modify the current
  10340. // session history entry to set
  10341. // a. cloned data as the state object,
  10342. // b. if the third argument was present, the absolute URL found in
  10343. // step 2
  10344. // Also clear the new history entry's POST data (see bug 580069).
  10345. // E. If aReplace is false (i.e. we're doing a pushState instead of a
  10346. // replaceState), notify bfcache that we've navigated to a new page.
  10347. // F. If the third argument is present, set the document's current address
  10348. // to the absolute URL found in step B. This is
  10349. // #url-and-history-update-steps step 4.
  10350. //
  10351. // It's important that this function not run arbitrary scripts after step 1
  10352. // and before completing step 5. For example, if a script called
  10353. // history.back() before we completed step 5, bfcache might destroy an
  10354. // active content viewer. Since EvictOutOfRangeContentViewers at the end of
  10355. // step E might run script, we can't just put a script blocker around the
  10356. // critical section.
  10357. //
  10358. // Note that we completely ignore the aTitle parameter.
  10359. nsresult rv;
  10360. // Don't clobber the load type of an existing network load.
  10361. AutoRestore<uint32_t> loadTypeResetter(mLoadType);
  10362. // pushState effectively becomes replaceState when we've started a network
  10363. // load but haven't adopted its document yet. This mirrors what we do with
  10364. // changes to the hash at this stage of the game.
  10365. if (JustStartedNetworkLoad()) {
  10366. aReplace = true;
  10367. }
  10368. nsCOMPtr<nsIDocument> document = GetDocument();
  10369. NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
  10370. // If we're being flooded with state change requests, we should abort early
  10371. // from the state change logic.
  10372. if (IsStateChangeFlooding()) {
  10373. // Report a warning to the console to tell developers why their navigations
  10374. // failed.
  10375. // Do this only if not yet marked reported so we only report it once per
  10376. // flood interval.
  10377. if (!mStateFloodGuardReported) {
  10378. nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
  10379. NS_LITERAL_CSTRING("PushState"),
  10380. document,
  10381. nsContentUtils::eDOM_PROPERTIES,
  10382. "PushStateFloodingPrevented");
  10383. mStateFloodGuardReported = true;
  10384. }
  10385. return NS_OK;
  10386. }
  10387. // Step A: Serialize aData using structured clone.
  10388. // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
  10389. // step 5.
  10390. nsCOMPtr<nsIStructuredCloneContainer> scContainer;
  10391. // scContainer->Init might cause arbitrary JS to run, and this code might
  10392. // navigate the page we're on, potentially to a different origin! (bug
  10393. // 634834) To protect against this, we abort if our principal changes due
  10394. // to the InitFromJSVal() call.
  10395. {
  10396. nsCOMPtr<nsIDocument> origDocument = GetDocument();
  10397. if (!origDocument) {
  10398. return NS_ERROR_DOM_SECURITY_ERR;
  10399. }
  10400. nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
  10401. scContainer = new nsStructuredCloneContainer();
  10402. rv = scContainer->InitFromJSVal(aData, aCx);
  10403. NS_ENSURE_SUCCESS(rv, rv);
  10404. nsCOMPtr<nsIDocument> newDocument = GetDocument();
  10405. if (!newDocument) {
  10406. return NS_ERROR_DOM_SECURITY_ERR;
  10407. }
  10408. nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal();
  10409. bool principalsEqual = false;
  10410. origPrincipal->Equals(newPrincipal, &principalsEqual);
  10411. NS_ENSURE_TRUE(principalsEqual, NS_ERROR_DOM_SECURITY_ERR);
  10412. }
  10413. // Check that the state object isn't too long.
  10414. // Default max length: 640k bytes.
  10415. int32_t maxStateObjSize =
  10416. Preferences::GetInt("browser.history.maxStateObjectSize", 0xA0000);
  10417. if (maxStateObjSize < 0) {
  10418. maxStateObjSize = 0;
  10419. }
  10420. uint64_t scSize;
  10421. rv = scContainer->GetSerializedNBytes(&scSize);
  10422. NS_ENSURE_SUCCESS(rv, rv);
  10423. NS_ENSURE_TRUE(scSize <= (uint32_t)maxStateObjSize, NS_ERROR_ILLEGAL_VALUE);
  10424. // Step B: Resolve aURL.
  10425. // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
  10426. // step 7.
  10427. bool equalURIs = true;
  10428. nsCOMPtr<nsIURI> currentURI;
  10429. if (sURIFixup && mCurrentURI) {
  10430. rv = sURIFixup->CreateExposableURI(mCurrentURI, getter_AddRefs(currentURI));
  10431. NS_ENSURE_SUCCESS(rv, rv);
  10432. } else {
  10433. currentURI = mCurrentURI;
  10434. }
  10435. nsCOMPtr<nsIURI> newURI;
  10436. if (aURL.Length() == 0) {
  10437. newURI = currentURI;
  10438. } else {
  10439. // 7.1: Resolve aURL relative to mURI
  10440. nsIURI* docBaseURI = document->GetDocBaseURI();
  10441. if (!docBaseURI) {
  10442. return NS_ERROR_FAILURE;
  10443. }
  10444. nsAutoCString spec;
  10445. docBaseURI->GetSpec(spec);
  10446. nsAutoCString charset;
  10447. rv = docBaseURI->GetOriginCharset(charset);
  10448. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  10449. rv = NS_NewURI(getter_AddRefs(newURI), aURL, charset.get(), docBaseURI);
  10450. // 7.2: If 7.1 fails, raise a SECURITY_ERR
  10451. if (NS_FAILED(rv)) {
  10452. return NS_ERROR_DOM_SECURITY_ERR;
  10453. }
  10454. // 7.4 and 7.5: Same-origin check.
  10455. if (!nsContentUtils::URIIsLocalFile(newURI)) {
  10456. // In addition to checking that the security manager says that
  10457. // the new URI has the same origin as our current URI, we also
  10458. // check that the two URIs have the same userpass. (The
  10459. // security manager says that |http://foo.com| and
  10460. // |http://me@foo.com| have the same origin.) currentURI
  10461. // won't contain the password part of the userpass, so this
  10462. // means that it's never valid to specify a password in a
  10463. // pushState or replaceState URI.
  10464. nsCOMPtr<nsIScriptSecurityManager> secMan =
  10465. do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
  10466. NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
  10467. // It's very important that we check that newURI is of the same
  10468. // origin as currentURI, not docBaseURI, because a page can
  10469. // set docBaseURI arbitrarily to any domain.
  10470. nsAutoCString currentUserPass, newUserPass;
  10471. NS_ENSURE_SUCCESS(currentURI->GetUserPass(currentUserPass),
  10472. NS_ERROR_FAILURE);
  10473. NS_ENSURE_SUCCESS(newURI->GetUserPass(newUserPass), NS_ERROR_FAILURE);
  10474. if (NS_FAILED(secMan->CheckSameOriginURI(currentURI, newURI, true)) ||
  10475. !currentUserPass.Equals(newUserPass)) {
  10476. return NS_ERROR_DOM_SECURITY_ERR;
  10477. }
  10478. } else {
  10479. // It's a file:// URI
  10480. nsCOMPtr<nsIScriptObjectPrincipal> docScriptObj =
  10481. do_QueryInterface(document);
  10482. if (!docScriptObj) {
  10483. return NS_ERROR_DOM_SECURITY_ERR;
  10484. }
  10485. nsCOMPtr<nsIPrincipal> principal = docScriptObj->GetPrincipal();
  10486. if (!principal ||
  10487. NS_FAILED(principal->CheckMayLoad(newURI, true, false))) {
  10488. return NS_ERROR_DOM_SECURITY_ERR;
  10489. }
  10490. }
  10491. if (currentURI) {
  10492. currentURI->Equals(newURI, &equalURIs);
  10493. } else {
  10494. equalURIs = false;
  10495. }
  10496. } // end of same-origin check
  10497. // Step 8: call "URL and history update steps"
  10498. rv = UpdateURLAndHistory(document, newURI, scContainer, aTitle, aReplace,
  10499. currentURI, equalURIs);
  10500. NS_ENSURE_SUCCESS(rv, rv);
  10501. return NS_OK;
  10502. }
  10503. nsresult
  10504. nsDocShell::UpdateURLAndHistory(nsIDocument* aDocument, nsIURI* aNewURI,
  10505. nsIStructuredCloneContainer* aData,
  10506. const nsAString& aTitle, bool aReplace,
  10507. nsIURI* aCurrentURI, bool aEqualURIs)
  10508. {
  10509. // Implements
  10510. // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
  10511. // Step 2, if aReplace is false: Create a new entry in the session
  10512. // history. This will erase all SHEntries after the new entry and make this
  10513. // entry the current one. This operation may modify mOSHE, which we need
  10514. // later, so we keep a reference here.
  10515. NS_ENSURE_TRUE(mOSHE || aReplace, NS_ERROR_FAILURE);
  10516. nsCOMPtr<nsISHEntry> oldOSHE = mOSHE;
  10517. mLoadType = LOAD_PUSHSTATE;
  10518. nsCOMPtr<nsISHEntry> newSHEntry;
  10519. if (!aReplace) {
  10520. // Step 2.
  10521. // Save the current scroll position (bug 590573). Step 2.3.
  10522. nscoord cx = 0, cy = 0;
  10523. GetCurScrollPos(ScrollOrientation_X, &cx);
  10524. GetCurScrollPos(ScrollOrientation_Y, &cy);
  10525. mOSHE->SetScrollPosition(cx, cy);
  10526. bool scrollRestorationIsManual = false;
  10527. mOSHE->GetScrollRestorationIsManual(&scrollRestorationIsManual);
  10528. // Since we're not changing which page we have loaded, pass
  10529. // true for aCloneChildren.
  10530. nsresult rv = AddToSessionHistory(aNewURI, nullptr,
  10531. aDocument->NodePrincipal(), // triggeringPrincipal
  10532. nullptr, true,
  10533. getter_AddRefs(newSHEntry));
  10534. NS_ENSURE_SUCCESS(rv, rv);
  10535. NS_ENSURE_TRUE(newSHEntry, NS_ERROR_FAILURE);
  10536. // Session history entries created by pushState inherit scroll restoration
  10537. // mode from the current entry.
  10538. newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual);
  10539. // Link the new SHEntry to the old SHEntry's BFCache entry, since the
  10540. // two entries correspond to the same document.
  10541. NS_ENSURE_SUCCESS(newSHEntry->AdoptBFCacheEntry(oldOSHE), NS_ERROR_FAILURE);
  10542. // Set the new SHEntry's title (bug 655273).
  10543. nsString title;
  10544. mOSHE->GetTitle(getter_Copies(title));
  10545. newSHEntry->SetTitle(title);
  10546. // AddToSessionHistory may not modify mOSHE. In case it doesn't,
  10547. // we'll just set mOSHE here.
  10548. mOSHE = newSHEntry;
  10549. } else {
  10550. // Step 3.
  10551. newSHEntry = mOSHE;
  10552. // Since we're not changing which page we have loaded, pass
  10553. if (!newSHEntry) {
  10554. nsresult rv = AddToSessionHistory(
  10555. aNewURI, nullptr,
  10556. aDocument->NodePrincipal(), // triggeringPrincipal
  10557. nullptr, true, getter_AddRefs(newSHEntry));
  10558. NS_ENSURE_SUCCESS(rv, rv);
  10559. mOSHE = newSHEntry;
  10560. }
  10561. newSHEntry->SetURI(aNewURI);
  10562. newSHEntry->SetOriginalURI(aNewURI);
  10563. newSHEntry->SetLoadReplace(false);
  10564. }
  10565. // Step 2.4 and 3: Modify new/original session history entry and clear its
  10566. // POST data, if there is any.
  10567. newSHEntry->SetStateData(aData);
  10568. newSHEntry->SetPostData(nullptr);
  10569. // If this push/replaceState changed the document's current URI and the new
  10570. // URI differs from the old URI in more than the hash, or if the old
  10571. // SHEntry's URI was modified in this way by a push/replaceState call
  10572. // set URIWasModified to true for the current SHEntry (bug 669671).
  10573. bool sameExceptHashes = true, oldURIWasModified = false;
  10574. aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes);
  10575. // mOSHE might be null on replace. Only check if we're not replacing.
  10576. if (oldOSHE) {
  10577. oldOSHE->GetURIWasModified(&oldURIWasModified);
  10578. }
  10579. newSHEntry->SetURIWasModified(!sameExceptHashes || oldURIWasModified);
  10580. // Step E as described at the top of AddState: If aReplace is false,
  10581. // indicating that we're doing a pushState rather than a replaceState, notify
  10582. // bfcache that we've added a page to the history so it can evict content
  10583. // viewers if appropriate. Otherwise call ReplaceEntry so that we notify
  10584. // nsIHistoryListeners that an entry was replaced. We may not have a root
  10585. // session history if this call is coming from a document.open() in a docshell
  10586. // subtree that disables session history.
  10587. nsCOMPtr<nsISHistory> rootSH;
  10588. GetRootSessionHistory(getter_AddRefs(rootSH));
  10589. NS_ENSURE_TRUE(rootSH, NS_ERROR_UNEXPECTED);
  10590. nsCOMPtr<nsISHistoryInternal> internalSH = do_QueryInterface(rootSH);
  10591. NS_ENSURE_TRUE(internalSH, NS_ERROR_UNEXPECTED);
  10592. nsresult rv;
  10593. if (rootSH) {
  10594. if (!aReplace) {
  10595. int32_t curIndex = -1;
  10596. rv = rootSH->GetIndex(&curIndex);
  10597. if (NS_SUCCEEDED(rv) && curIndex > -1) {
  10598. internalSH->EvictOutOfRangeContentViewers(curIndex);
  10599. }
  10600. } else {
  10601. nsCOMPtr<nsISHEntry> rootSHEntry = GetRootSHEntry(newSHEntry);
  10602. int32_t index = -1;
  10603. rv = rootSH->GetIndexOfEntry(rootSHEntry, &index);
  10604. if (NS_SUCCEEDED(rv) && index > -1) {
  10605. internalSH->ReplaceEntry(index, rootSHEntry);
  10606. }
  10607. }
  10608. }
  10609. // Step 4: If the document's URI changed, update document's URI and update
  10610. // global history.
  10611. //
  10612. // We need to call FireOnLocationChange so that the browser's address bar
  10613. // gets updated and the back button is enabled, but we only need to
  10614. // explicitly call FireOnLocationChange if we're not calling SetCurrentURI,
  10615. // since SetCurrentURI will call FireOnLocationChange for us.
  10616. //
  10617. // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass
  10618. // nullptr for aRequest param to FireOnLocationChange(...). Such an update
  10619. // notification is allowed only when we know docshell is not loading a new
  10620. // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise,
  10621. // FireOnLocationChange(...) breaks security UI.
  10622. if (!aEqualURIs) {
  10623. aDocument->SetDocumentURI(aNewURI);
  10624. // We can't trust SetCurrentURI to do always fire locationchange events
  10625. // when we expect it to, so we hack around that by doing it ourselves...
  10626. SetCurrentURI(aNewURI, nullptr, false, LOCATION_CHANGE_SAME_DOCUMENT);
  10627. if (mLoadType != LOAD_ERROR_PAGE) {
  10628. FireDummyOnLocationChange();
  10629. }
  10630. AddURIVisit(aNewURI, aCurrentURI, aCurrentURI, 0);
  10631. // AddURIVisit doesn't set the title for the new URI in global history,
  10632. // so do that here.
  10633. if (mUseGlobalHistory && !UsePrivateBrowsing()) {
  10634. nsCOMPtr<IHistory> history = services::GetHistoryService();
  10635. if (history) {
  10636. history->SetURITitle(aNewURI, mTitle);
  10637. } else if (mGlobalHistory) {
  10638. mGlobalHistory->SetPageTitle(aNewURI, mTitle);
  10639. }
  10640. }
  10641. // Inform the favicon service that our old favicon applies to this new
  10642. // URI.
  10643. CopyFavicon(aCurrentURI, aNewURI, aDocument->NodePrincipal(), UsePrivateBrowsing());
  10644. } else {
  10645. FireDummyOnLocationChange();
  10646. }
  10647. aDocument->SetStateObject(aData);
  10648. return NS_OK;
  10649. }
  10650. NS_IMETHODIMP
  10651. nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual)
  10652. {
  10653. *aIsManual = false;
  10654. if (mOSHE) {
  10655. mOSHE->GetScrollRestorationIsManual(aIsManual);
  10656. }
  10657. return NS_OK;
  10658. }
  10659. NS_IMETHODIMP
  10660. nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual)
  10661. {
  10662. if (mOSHE) {
  10663. mOSHE->SetScrollRestorationIsManual(aIsManual);
  10664. }
  10665. return NS_OK;
  10666. }
  10667. bool
  10668. nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI)
  10669. {
  10670. // I believe none of the about: urls should go in the history. But then
  10671. // that could just be me... If the intent is only deny about:blank then we
  10672. // should just do a spec compare, rather than two gets of the scheme and
  10673. // then the path. -Gagan
  10674. nsresult rv;
  10675. nsAutoCString buf;
  10676. rv = aURI->GetScheme(buf);
  10677. if (NS_FAILED(rv)) {
  10678. return false;
  10679. }
  10680. if (buf.EqualsLiteral("about")) {
  10681. rv = aURI->GetPath(buf);
  10682. if (NS_FAILED(rv)) {
  10683. return false;
  10684. }
  10685. if (buf.EqualsLiteral("blank") || buf.EqualsLiteral("logopage") ||
  10686. (buf.EqualsLiteral("newtab") &&
  10687. !Preferences::GetBool("browser.newtabpage.add_to_session_history", false))) {
  10688. return false;
  10689. }
  10690. }
  10691. return true;
  10692. }
  10693. nsresult
  10694. nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
  10695. nsIPrincipal* aTriggeringPrincipal,
  10696. nsIPrincipal* aPrincipalToInherit,
  10697. bool aCloneChildren,
  10698. nsISHEntry** aNewEntry)
  10699. {
  10700. NS_PRECONDITION(aURI, "uri is null");
  10701. NS_PRECONDITION(!aChannel || !aTriggeringPrincipal, "Shouldn't have both set");
  10702. #if defined(DEBUG)
  10703. if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)) {
  10704. nsAutoCString chanName;
  10705. if (aChannel) {
  10706. aChannel->GetName(chanName);
  10707. } else {
  10708. chanName.AssignLiteral("<no channel>");
  10709. }
  10710. MOZ_LOG(gDocShellLog, LogLevel::Debug,
  10711. ("nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n",
  10712. this, aURI->GetSpecOrDefault().get(), chanName.get()));
  10713. }
  10714. #endif
  10715. nsresult rv = NS_OK;
  10716. nsCOMPtr<nsISHEntry> entry;
  10717. bool shouldPersist;
  10718. shouldPersist = ShouldAddToSessionHistory(aURI);
  10719. // Get a handle to the root docshell
  10720. nsCOMPtr<nsIDocShellTreeItem> root;
  10721. GetSameTypeRootTreeItem(getter_AddRefs(root));
  10722. /*
  10723. * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use
  10724. * the existing SH entry in the page and replace the url and
  10725. * other vitalities.
  10726. */
  10727. if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY) &&
  10728. root != static_cast<nsIDocShellTreeItem*>(this)) {
  10729. // This is a subframe
  10730. entry = mOSHE;
  10731. nsCOMPtr<nsISHContainer> shContainer(do_QueryInterface(entry));
  10732. if (shContainer) {
  10733. int32_t childCount = 0;
  10734. shContainer->GetChildCount(&childCount);
  10735. // Remove all children of this entry
  10736. for (int32_t i = childCount - 1; i >= 0; i--) {
  10737. nsCOMPtr<nsISHEntry> child;
  10738. shContainer->GetChildAt(i, getter_AddRefs(child));
  10739. shContainer->RemoveChild(child);
  10740. }
  10741. entry->AbandonBFCacheEntry();
  10742. }
  10743. }
  10744. // Create a new entry if necessary.
  10745. if (!entry) {
  10746. entry = do_CreateInstance(NS_SHENTRY_CONTRACTID);
  10747. if (!entry) {
  10748. return NS_ERROR_OUT_OF_MEMORY;
  10749. }
  10750. }
  10751. // Get the post data & referrer
  10752. nsCOMPtr<nsIInputStream> inputStream;
  10753. nsCOMPtr<nsIURI> originalURI;
  10754. bool loadReplace = false;
  10755. nsCOMPtr<nsIURI> referrerURI;
  10756. uint32_t referrerPolicy = mozilla::net::RP_Default;
  10757. nsCOMPtr<nsISupports> cacheKey;
  10758. nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal;
  10759. nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
  10760. bool expired = false;
  10761. bool discardLayoutState = false;
  10762. nsCOMPtr<nsICacheInfoChannel> cacheChannel;
  10763. if (aChannel) {
  10764. cacheChannel = do_QueryInterface(aChannel);
  10765. /* If there is a caching channel, get the Cache Key and store it
  10766. * in SH.
  10767. */
  10768. if (cacheChannel) {
  10769. cacheChannel->GetCacheKey(getter_AddRefs(cacheKey));
  10770. }
  10771. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
  10772. // Check if the httpChannel is hiding under a multipartChannel
  10773. if (!httpChannel) {
  10774. GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
  10775. }
  10776. if (httpChannel) {
  10777. nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
  10778. if (uploadChannel) {
  10779. uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
  10780. }
  10781. httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
  10782. uint32_t loadFlags;
  10783. aChannel->GetLoadFlags(&loadFlags);
  10784. loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
  10785. httpChannel->GetReferrer(getter_AddRefs(referrerURI));
  10786. httpChannel->GetReferrerPolicy(&referrerPolicy);
  10787. discardLayoutState = ShouldDiscardLayoutState(httpChannel);
  10788. }
  10789. nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
  10790. if (loadInfo) {
  10791. if (!triggeringPrincipal) {
  10792. triggeringPrincipal = loadInfo->TriggeringPrincipal();
  10793. }
  10794. // For now keep storing just the principal in the SHEntry.
  10795. if (!principalToInherit) {
  10796. if (loadInfo->GetLoadingSandboxed()) {
  10797. if (loadInfo->LoadingPrincipal()) {
  10798. principalToInherit = nsNullPrincipal::CreateWithInheritedAttributes(
  10799. loadInfo->LoadingPrincipal());
  10800. } else {
  10801. // get the OriginAttributes
  10802. NeckoOriginAttributes nAttrs;
  10803. loadInfo->GetOriginAttributes(&nAttrs);
  10804. PrincipalOriginAttributes pAttrs;
  10805. pAttrs.InheritFromNecko(nAttrs);
  10806. principalToInherit = nsNullPrincipal::Create(pAttrs);
  10807. }
  10808. } else {
  10809. principalToInherit = loadInfo->PrincipalToInherit();
  10810. }
  10811. }
  10812. }
  10813. }
  10814. // Title is set in nsDocShell::SetTitle()
  10815. entry->Create(aURI, // uri
  10816. EmptyString(), // Title
  10817. inputStream, // Post data stream
  10818. nullptr, // LayoutHistory state
  10819. cacheKey, // CacheKey
  10820. mContentTypeHint, // Content-type
  10821. triggeringPrincipal, // Channel or provided principal
  10822. principalToInherit,
  10823. mHistoryID,
  10824. mDynamicallyCreated);
  10825. entry->SetOriginalURI(originalURI);
  10826. entry->SetLoadReplace(loadReplace);
  10827. entry->SetReferrerURI(referrerURI);
  10828. entry->SetReferrerPolicy(referrerPolicy);
  10829. nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
  10830. if (inStrmChan) {
  10831. bool isSrcdocChannel;
  10832. inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
  10833. if (isSrcdocChannel) {
  10834. nsAutoString srcdoc;
  10835. inStrmChan->GetSrcdocData(srcdoc);
  10836. entry->SetSrcdocData(srcdoc);
  10837. nsCOMPtr<nsIURI> baseURI;
  10838. inStrmChan->GetBaseURI(getter_AddRefs(baseURI));
  10839. entry->SetBaseURI(baseURI);
  10840. }
  10841. }
  10842. /* If cache got a 'no-store', ask SH not to store
  10843. * HistoryLayoutState. By default, SH will set this
  10844. * flag to true and save HistoryLayoutState.
  10845. */
  10846. if (discardLayoutState) {
  10847. entry->SetSaveLayoutStateFlag(false);
  10848. }
  10849. if (cacheChannel) {
  10850. // Check if the page has expired from cache
  10851. uint32_t expTime = 0;
  10852. cacheChannel->GetCacheTokenExpirationTime(&expTime);
  10853. uint32_t now = PRTimeToSeconds(PR_Now());
  10854. if (expTime <= now) {
  10855. expired = true;
  10856. }
  10857. }
  10858. if (expired) {
  10859. entry->SetExpirationStatus(true);
  10860. }
  10861. if (root == static_cast<nsIDocShellTreeItem*>(this) && mSessionHistory) {
  10862. // If we need to clone our children onto the new session
  10863. // history entry, do so now.
  10864. if (aCloneChildren && mOSHE) {
  10865. uint32_t cloneID;
  10866. mOSHE->GetID(&cloneID);
  10867. nsCOMPtr<nsISHEntry> newEntry;
  10868. CloneAndReplace(mOSHE, this, cloneID, entry, true,
  10869. getter_AddRefs(newEntry));
  10870. NS_ASSERTION(entry == newEntry,
  10871. "The new session history should be in the new entry");
  10872. }
  10873. // This is the root docshell
  10874. bool addToSHistory = !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY);
  10875. if (!addToSHistory) {
  10876. // Replace current entry in session history; If the requested index is
  10877. // valid, it indicates the loading was triggered by a history load, and
  10878. // we should replace the entry at requested index instead.
  10879. int32_t index = 0;
  10880. mSessionHistory->GetRequestedIndex(&index);
  10881. if (index == -1) {
  10882. mSessionHistory->GetIndex(&index);
  10883. }
  10884. nsCOMPtr<nsISHistoryInternal> shPrivate =
  10885. do_QueryInterface(mSessionHistory);
  10886. // Replace the current entry with the new entry
  10887. if (index >= 0) {
  10888. if (shPrivate) {
  10889. rv = shPrivate->ReplaceEntry(index, entry);
  10890. }
  10891. } else {
  10892. // If we're trying to replace an inexistant shistory entry, append.
  10893. addToSHistory = true;
  10894. }
  10895. }
  10896. if (addToSHistory) {
  10897. // Add to session history
  10898. nsCOMPtr<nsISHistoryInternal> shPrivate =
  10899. do_QueryInterface(mSessionHistory);
  10900. NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE);
  10901. mSessionHistory->GetIndex(&mPreviousTransIndex);
  10902. rv = shPrivate->AddEntry(entry, shouldPersist);
  10903. mSessionHistory->GetIndex(&mLoadedTransIndex);
  10904. #ifdef DEBUG_PAGE_CACHE
  10905. printf("Previous index: %d, Loaded index: %d\n\n",
  10906. mPreviousTransIndex, mLoadedTransIndex);
  10907. #endif
  10908. }
  10909. } else {
  10910. // This is a subframe.
  10911. if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
  10912. rv = AddChildSHEntryToParent(entry, mChildOffset, aCloneChildren);
  10913. }
  10914. }
  10915. // Return the new SH entry...
  10916. if (aNewEntry) {
  10917. *aNewEntry = nullptr;
  10918. if (NS_SUCCEEDED(rv)) {
  10919. entry.forget(aNewEntry);
  10920. }
  10921. }
  10922. return rv;
  10923. }
  10924. nsresult
  10925. nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
  10926. {
  10927. if (!IsNavigationAllowed()) {
  10928. return NS_OK;
  10929. }
  10930. nsCOMPtr<nsIURI> uri;
  10931. nsCOMPtr<nsIURI> originalURI;
  10932. bool loadReplace = false;
  10933. nsCOMPtr<nsIInputStream> postData;
  10934. nsCOMPtr<nsIURI> referrerURI;
  10935. uint32_t referrerPolicy;
  10936. nsAutoCString contentType;
  10937. nsCOMPtr<nsIPrincipal> triggeringPrincipal;
  10938. nsCOMPtr<nsIPrincipal> principalToInherit;
  10939. NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE);
  10940. NS_ENSURE_SUCCESS(aEntry->GetURI(getter_AddRefs(uri)), NS_ERROR_FAILURE);
  10941. NS_ENSURE_SUCCESS(aEntry->GetOriginalURI(getter_AddRefs(originalURI)),
  10942. NS_ERROR_FAILURE);
  10943. NS_ENSURE_SUCCESS(aEntry->GetLoadReplace(&loadReplace),
  10944. NS_ERROR_FAILURE);
  10945. NS_ENSURE_SUCCESS(aEntry->GetReferrerURI(getter_AddRefs(referrerURI)),
  10946. NS_ERROR_FAILURE);
  10947. NS_ENSURE_SUCCESS(aEntry->GetReferrerPolicy(&referrerPolicy),
  10948. NS_ERROR_FAILURE);
  10949. NS_ENSURE_SUCCESS(aEntry->GetPostData(getter_AddRefs(postData)),
  10950. NS_ERROR_FAILURE);
  10951. NS_ENSURE_SUCCESS(aEntry->GetContentType(contentType), NS_ERROR_FAILURE);
  10952. NS_ENSURE_SUCCESS(aEntry->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal)),
  10953. NS_ERROR_FAILURE);
  10954. NS_ENSURE_SUCCESS(aEntry->GetPrincipalToInherit(getter_AddRefs(principalToInherit)),
  10955. NS_ERROR_FAILURE);
  10956. // Calling CreateAboutBlankContentViewer can set mOSHE to null, and if
  10957. // that's the only thing holding a ref to aEntry that will cause aEntry to
  10958. // die while we're loading it. So hold a strong ref to aEntry here, just
  10959. // in case.
  10960. nsCOMPtr<nsISHEntry> kungFuDeathGrip(aEntry);
  10961. bool isJS;
  10962. nsresult rv = uri->SchemeIs("javascript", &isJS);
  10963. if (NS_FAILED(rv) || isJS) {
  10964. // We're loading a URL that will execute script from inside asyncOpen.
  10965. // Replace the current document with about:blank now to prevent
  10966. // anything from the current document from leaking into any JavaScript
  10967. // code in the URL.
  10968. // Don't cache the presentation if we're going to just reload the
  10969. // current entry. Caching would lead to trying to save the different
  10970. // content viewers in the same nsISHEntry object.
  10971. rv = CreateAboutBlankContentViewer(principalToInherit, nullptr,
  10972. aEntry != mOSHE);
  10973. if (NS_FAILED(rv)) {
  10974. // The creation of the intermittent about:blank content
  10975. // viewer failed for some reason (potentially because the
  10976. // user prevented it). Interrupt the history load.
  10977. return NS_OK;
  10978. }
  10979. if (!triggeringPrincipal) {
  10980. // Ensure that we have a triggeringPrincipal. Otherwise javascript:
  10981. // URIs will pick it up from the about:blank page we just loaded,
  10982. // and we don't really want even that in this case.
  10983. triggeringPrincipal = nsNullPrincipal::CreateWithInheritedAttributes(this);
  10984. }
  10985. }
  10986. /* If there is a valid postdata *and* the user pressed
  10987. * reload or shift-reload, take user's permission before we
  10988. * repost the data to the server.
  10989. */
  10990. if ((aLoadType & LOAD_CMD_RELOAD) && postData) {
  10991. bool repost;
  10992. rv = ConfirmRepost(&repost);
  10993. if (NS_FAILED(rv)) {
  10994. return rv;
  10995. }
  10996. // If the user pressed cancel in the dialog, return. We're done here.
  10997. if (!repost) {
  10998. return NS_BINDING_ABORTED;
  10999. }
  11000. }
  11001. // Do not inherit principal from document (security-critical!);
  11002. uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
  11003. nsAutoString srcdoc;
  11004. bool isSrcdoc;
  11005. nsCOMPtr<nsIURI> baseURI;
  11006. aEntry->GetIsSrcdocEntry(&isSrcdoc);
  11007. if (isSrcdoc) {
  11008. aEntry->GetSrcdocData(srcdoc);
  11009. aEntry->GetBaseURI(getter_AddRefs(baseURI));
  11010. flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
  11011. } else {
  11012. srcdoc = NullString();
  11013. }
  11014. if (!triggeringPrincipal) {
  11015. triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
  11016. }
  11017. // Passing nullptr as aSourceDocShell gives the same behaviour as before
  11018. // aSourceDocShell was introduced. According to spec we should be passing
  11019. // the source browsing context that was used when the history entry was
  11020. // first created. bug 947716 has been created to address this issue.
  11021. rv = InternalLoad(uri,
  11022. originalURI,
  11023. loadReplace,
  11024. false, // Is from processing frame attributes
  11025. referrerURI,
  11026. referrerPolicy,
  11027. triggeringPrincipal,
  11028. principalToInherit,
  11029. flags,
  11030. EmptyString(), // No window target
  11031. contentType.get(), // Type hint
  11032. NullString(), // No forced file download
  11033. postData, // Post data stream
  11034. nullptr, // No headers stream
  11035. aLoadType, // Load type
  11036. aEntry, // SHEntry
  11037. true,
  11038. srcdoc,
  11039. nullptr, // Source docshell, see comment above
  11040. baseURI,
  11041. nullptr, // No nsIDocShell
  11042. nullptr); // No nsIRequest
  11043. return rv;
  11044. }
  11045. NS_IMETHODIMP
  11046. nsDocShell::GetShouldSaveLayoutState(bool* aShould)
  11047. {
  11048. *aShould = false;
  11049. if (mOSHE) {
  11050. // Don't capture historystate and save it in history
  11051. // if the page asked not to do so.
  11052. mOSHE->GetSaveLayoutStateFlag(aShould);
  11053. }
  11054. return NS_OK;
  11055. }
  11056. nsresult
  11057. nsDocShell::PersistLayoutHistoryState()
  11058. {
  11059. nsresult rv = NS_OK;
  11060. if (mOSHE) {
  11061. bool scrollRestorationIsManual = false;
  11062. mOSHE->GetScrollRestorationIsManual(&scrollRestorationIsManual);
  11063. nsCOMPtr<nsIPresShell> shell = GetPresShell();
  11064. nsCOMPtr<nsILayoutHistoryState> layoutState;
  11065. if (shell) {
  11066. rv = shell->CaptureHistoryState(getter_AddRefs(layoutState));
  11067. } else if (scrollRestorationIsManual) {
  11068. // Even if we don't have layout anymore, we may want to reset the current
  11069. // scroll state in layout history.
  11070. GetLayoutHistoryState(getter_AddRefs(layoutState));
  11071. }
  11072. if (scrollRestorationIsManual && layoutState) {
  11073. layoutState->ResetScrollState();
  11074. }
  11075. }
  11076. return rv;
  11077. }
  11078. /* static */ nsresult
  11079. nsDocShell::WalkHistoryEntries(nsISHEntry* aRootEntry,
  11080. nsDocShell* aRootShell,
  11081. WalkHistoryEntriesFunc aCallback,
  11082. void* aData)
  11083. {
  11084. NS_ENSURE_TRUE(aRootEntry, NS_ERROR_FAILURE);
  11085. nsCOMPtr<nsISHContainer> container(do_QueryInterface(aRootEntry));
  11086. if (!container) {
  11087. return NS_ERROR_FAILURE;
  11088. }
  11089. int32_t childCount;
  11090. container->GetChildCount(&childCount);
  11091. for (int32_t i = 0; i < childCount; i++) {
  11092. nsCOMPtr<nsISHEntry> childEntry;
  11093. container->GetChildAt(i, getter_AddRefs(childEntry));
  11094. if (!childEntry) {
  11095. // childEntry can be null for valid reasons, for example if the
  11096. // docshell at index i never loaded anything useful.
  11097. // Remember to clone also nulls in the child array (bug 464064).
  11098. aCallback(nullptr, nullptr, i, aData);
  11099. continue;
  11100. }
  11101. nsDocShell* childShell = nullptr;
  11102. if (aRootShell) {
  11103. // Walk the children of aRootShell and see if one of them
  11104. // has srcChild as a SHEntry.
  11105. nsTObserverArray<nsDocLoader*>::ForwardIterator iter(
  11106. aRootShell->mChildList);
  11107. while (iter.HasMore()) {
  11108. nsDocShell* child = static_cast<nsDocShell*>(iter.GetNext());
  11109. if (child->HasHistoryEntry(childEntry)) {
  11110. childShell = child;
  11111. break;
  11112. }
  11113. }
  11114. }
  11115. nsresult rv = aCallback(childEntry, childShell, i, aData);
  11116. NS_ENSURE_SUCCESS(rv, rv);
  11117. }
  11118. return NS_OK;
  11119. }
  11120. // callback data for WalkHistoryEntries
  11121. struct MOZ_STACK_CLASS CloneAndReplaceData
  11122. {
  11123. CloneAndReplaceData(uint32_t aCloneID, nsISHEntry* aReplaceEntry,
  11124. bool aCloneChildren, nsISHEntry* aDestTreeParent)
  11125. : cloneID(aCloneID)
  11126. , cloneChildren(aCloneChildren)
  11127. , replaceEntry(aReplaceEntry)
  11128. , destTreeParent(aDestTreeParent)
  11129. {
  11130. }
  11131. uint32_t cloneID;
  11132. bool cloneChildren;
  11133. nsISHEntry* replaceEntry;
  11134. nsISHEntry* destTreeParent;
  11135. nsCOMPtr<nsISHEntry> resultEntry;
  11136. };
  11137. /* static */ nsresult
  11138. nsDocShell::CloneAndReplaceChild(nsISHEntry* aEntry, nsDocShell* aShell,
  11139. int32_t aEntryIndex, void* aData)
  11140. {
  11141. nsCOMPtr<nsISHEntry> dest;
  11142. CloneAndReplaceData* data = static_cast<CloneAndReplaceData*>(aData);
  11143. uint32_t cloneID = data->cloneID;
  11144. nsISHEntry* replaceEntry = data->replaceEntry;
  11145. nsCOMPtr<nsISHContainer> container = do_QueryInterface(data->destTreeParent);
  11146. if (!aEntry) {
  11147. if (container) {
  11148. container->AddChild(nullptr, aEntryIndex);
  11149. }
  11150. return NS_OK;
  11151. }
  11152. uint32_t srcID;
  11153. aEntry->GetID(&srcID);
  11154. nsresult rv = NS_OK;
  11155. if (srcID == cloneID) {
  11156. // Replace the entry
  11157. dest = replaceEntry;
  11158. } else {
  11159. // Clone the SHEntry...
  11160. rv = aEntry->Clone(getter_AddRefs(dest));
  11161. NS_ENSURE_SUCCESS(rv, rv);
  11162. }
  11163. dest->SetIsSubFrame(true);
  11164. if (srcID != cloneID || data->cloneChildren) {
  11165. // Walk the children
  11166. CloneAndReplaceData childData(cloneID, replaceEntry,
  11167. data->cloneChildren, dest);
  11168. rv = WalkHistoryEntries(aEntry, aShell,
  11169. CloneAndReplaceChild, &childData);
  11170. NS_ENSURE_SUCCESS(rv, rv);
  11171. }
  11172. if (srcID != cloneID && aShell) {
  11173. aShell->SwapHistoryEntries(aEntry, dest);
  11174. }
  11175. if (container) {
  11176. container->AddChild(dest, aEntryIndex);
  11177. }
  11178. data->resultEntry = dest;
  11179. return rv;
  11180. }
  11181. /* static */ nsresult
  11182. nsDocShell::CloneAndReplace(nsISHEntry* aSrcEntry,
  11183. nsDocShell* aSrcShell,
  11184. uint32_t aCloneID,
  11185. nsISHEntry* aReplaceEntry,
  11186. bool aCloneChildren,
  11187. nsISHEntry** aResultEntry)
  11188. {
  11189. NS_ENSURE_ARG_POINTER(aResultEntry);
  11190. NS_ENSURE_TRUE(aReplaceEntry, NS_ERROR_FAILURE);
  11191. CloneAndReplaceData data(aCloneID, aReplaceEntry, aCloneChildren, nullptr);
  11192. nsresult rv = CloneAndReplaceChild(aSrcEntry, aSrcShell, 0, &data);
  11193. data.resultEntry.swap(*aResultEntry);
  11194. return rv;
  11195. }
  11196. void
  11197. nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry, nsISHEntry* aNewEntry)
  11198. {
  11199. if (aOldEntry == mOSHE) {
  11200. mOSHE = aNewEntry;
  11201. }
  11202. if (aOldEntry == mLSHE) {
  11203. mLSHE = aNewEntry;
  11204. }
  11205. }
  11206. struct SwapEntriesData
  11207. {
  11208. nsDocShell* ignoreShell; // constant; the shell to ignore
  11209. nsISHEntry* destTreeRoot; // constant; the root of the dest tree
  11210. nsISHEntry* destTreeParent; // constant; the node under destTreeRoot
  11211. // whose children will correspond to aEntry
  11212. };
  11213. nsresult
  11214. nsDocShell::SetChildHistoryEntry(nsISHEntry* aEntry, nsDocShell* aShell,
  11215. int32_t aEntryIndex, void* aData)
  11216. {
  11217. SwapEntriesData* data = static_cast<SwapEntriesData*>(aData);
  11218. nsDocShell* ignoreShell = data->ignoreShell;
  11219. if (!aShell || aShell == ignoreShell) {
  11220. return NS_OK;
  11221. }
  11222. nsISHEntry* destTreeRoot = data->destTreeRoot;
  11223. nsCOMPtr<nsISHEntry> destEntry;
  11224. nsCOMPtr<nsISHContainer> container = do_QueryInterface(data->destTreeParent);
  11225. if (container) {
  11226. // aEntry is a clone of some child of destTreeParent, but since the
  11227. // trees aren't necessarily in sync, we'll have to locate it.
  11228. // Note that we could set aShell's entry to null if we don't find a
  11229. // corresponding entry under destTreeParent.
  11230. uint32_t targetID, id;
  11231. aEntry->GetID(&targetID);
  11232. // First look at the given index, since this is the common case.
  11233. nsCOMPtr<nsISHEntry> entry;
  11234. container->GetChildAt(aEntryIndex, getter_AddRefs(entry));
  11235. if (entry && NS_SUCCEEDED(entry->GetID(&id)) && id == targetID) {
  11236. destEntry.swap(entry);
  11237. } else {
  11238. int32_t childCount;
  11239. container->GetChildCount(&childCount);
  11240. for (int32_t i = 0; i < childCount; ++i) {
  11241. container->GetChildAt(i, getter_AddRefs(entry));
  11242. if (!entry) {
  11243. continue;
  11244. }
  11245. entry->GetID(&id);
  11246. if (id == targetID) {
  11247. destEntry.swap(entry);
  11248. break;
  11249. }
  11250. }
  11251. }
  11252. } else {
  11253. destEntry = destTreeRoot;
  11254. }
  11255. aShell->SwapHistoryEntries(aEntry, destEntry);
  11256. // Now handle the children of aEntry.
  11257. SwapEntriesData childData = { ignoreShell, destTreeRoot, destEntry };
  11258. return WalkHistoryEntries(aEntry, aShell, SetChildHistoryEntry, &childData);
  11259. }
  11260. static nsISHEntry*
  11261. GetRootSHEntry(nsISHEntry* aEntry)
  11262. {
  11263. nsCOMPtr<nsISHEntry> rootEntry = aEntry;
  11264. nsISHEntry* result = nullptr;
  11265. while (rootEntry) {
  11266. result = rootEntry;
  11267. result->GetParent(getter_AddRefs(rootEntry));
  11268. }
  11269. return result;
  11270. }
  11271. void
  11272. nsDocShell::SetHistoryEntry(nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry)
  11273. {
  11274. // We need to sync up the docshell and session history trees for
  11275. // subframe navigation. If the load was in a subframe, we forward up to
  11276. // the root docshell, which will then recursively sync up all docshells
  11277. // to their corresponding entries in the new session history tree.
  11278. // If we don't do this, then we can cache a content viewer on the wrong
  11279. // cloned entry, and subsequently restore it at the wrong time.
  11280. nsISHEntry* newRootEntry = GetRootSHEntry(aEntry);
  11281. if (newRootEntry) {
  11282. // newRootEntry is now the new root entry.
  11283. // Find the old root entry as well.
  11284. // Need a strong ref. on |oldRootEntry| so it isn't destroyed when
  11285. // SetChildHistoryEntry() does SwapHistoryEntries() (bug 304639).
  11286. nsCOMPtr<nsISHEntry> oldRootEntry = GetRootSHEntry(*aPtr);
  11287. if (oldRootEntry) {
  11288. nsCOMPtr<nsIDocShellTreeItem> rootAsItem;
  11289. GetSameTypeRootTreeItem(getter_AddRefs(rootAsItem));
  11290. nsCOMPtr<nsIDocShell> rootShell = do_QueryInterface(rootAsItem);
  11291. if (rootShell) { // if we're the root just set it, nothing to swap
  11292. SwapEntriesData data = { this, newRootEntry };
  11293. nsIDocShell* rootIDocShell = static_cast<nsIDocShell*>(rootShell);
  11294. nsDocShell* rootDocShell = static_cast<nsDocShell*>(rootIDocShell);
  11295. #ifdef DEBUG
  11296. nsresult rv =
  11297. #endif
  11298. SetChildHistoryEntry(oldRootEntry, rootDocShell, 0, &data);
  11299. NS_ASSERTION(NS_SUCCEEDED(rv), "SetChildHistoryEntry failed");
  11300. }
  11301. }
  11302. }
  11303. *aPtr = aEntry;
  11304. }
  11305. nsresult
  11306. nsDocShell::GetRootSessionHistory(nsISHistory** aReturn)
  11307. {
  11308. nsresult rv;
  11309. nsCOMPtr<nsIDocShellTreeItem> root;
  11310. // Get the root docshell
  11311. rv = GetSameTypeRootTreeItem(getter_AddRefs(root));
  11312. // QI to nsIWebNavigation
  11313. nsCOMPtr<nsIWebNavigation> rootAsWebnav(do_QueryInterface(root));
  11314. if (rootAsWebnav) {
  11315. // Get the handle to SH from the root docshell
  11316. rv = rootAsWebnav->GetSessionHistory(aReturn);
  11317. }
  11318. return rv;
  11319. }
  11320. nsresult
  11321. nsDocShell::GetHttpChannel(nsIChannel* aChannel, nsIHttpChannel** aReturn)
  11322. {
  11323. NS_ENSURE_ARG_POINTER(aReturn);
  11324. if (!aChannel) {
  11325. return NS_ERROR_FAILURE;
  11326. }
  11327. nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel));
  11328. if (multiPartChannel) {
  11329. nsCOMPtr<nsIChannel> baseChannel;
  11330. multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel));
  11331. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel));
  11332. *aReturn = httpChannel;
  11333. NS_IF_ADDREF(*aReturn);
  11334. }
  11335. return NS_OK;
  11336. }
  11337. bool
  11338. nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel)
  11339. {
  11340. // By default layout State will be saved.
  11341. if (!aChannel) {
  11342. return false;
  11343. }
  11344. // figure out if SH should be saving layout state
  11345. bool noStore = false;
  11346. aChannel->IsNoStoreResponse(&noStore);
  11347. return noStore;
  11348. }
  11349. NS_IMETHODIMP
  11350. nsDocShell::GetEditor(nsIEditor** aEditor)
  11351. {
  11352. NS_ENSURE_ARG_POINTER(aEditor);
  11353. if (!mEditorData) {
  11354. *aEditor = nullptr;
  11355. return NS_OK;
  11356. }
  11357. return mEditorData->GetEditor(aEditor);
  11358. }
  11359. NS_IMETHODIMP
  11360. nsDocShell::SetEditor(nsIEditor* aEditor)
  11361. {
  11362. nsresult rv = EnsureEditorData();
  11363. if (NS_FAILED(rv)) {
  11364. return rv;
  11365. }
  11366. return mEditorData->SetEditor(aEditor);
  11367. }
  11368. NS_IMETHODIMP
  11369. nsDocShell::GetEditable(bool* aEditable)
  11370. {
  11371. NS_ENSURE_ARG_POINTER(aEditable);
  11372. *aEditable = mEditorData && mEditorData->GetEditable();
  11373. return NS_OK;
  11374. }
  11375. NS_IMETHODIMP
  11376. nsDocShell::GetHasEditingSession(bool* aHasEditingSession)
  11377. {
  11378. NS_ENSURE_ARG_POINTER(aHasEditingSession);
  11379. if (mEditorData) {
  11380. nsCOMPtr<nsIEditingSession> editingSession;
  11381. mEditorData->GetEditingSession(getter_AddRefs(editingSession));
  11382. *aHasEditingSession = (editingSession.get() != nullptr);
  11383. } else {
  11384. *aHasEditingSession = false;
  11385. }
  11386. return NS_OK;
  11387. }
  11388. NS_IMETHODIMP
  11389. nsDocShell::MakeEditable(bool aInWaitForUriLoad)
  11390. {
  11391. nsresult rv = EnsureEditorData();
  11392. if (NS_FAILED(rv)) {
  11393. return rv;
  11394. }
  11395. return mEditorData->MakeEditable(aInWaitForUriLoad);
  11396. }
  11397. bool
  11398. nsDocShell::ChannelIsPost(nsIChannel* aChannel)
  11399. {
  11400. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
  11401. if (!httpChannel) {
  11402. return false;
  11403. }
  11404. nsAutoCString method;
  11405. httpChannel->GetRequestMethod(method);
  11406. return method.EqualsLiteral("POST");
  11407. }
  11408. void
  11409. nsDocShell::ExtractLastVisit(nsIChannel* aChannel,
  11410. nsIURI** aURI,
  11411. uint32_t* aChannelRedirectFlags)
  11412. {
  11413. nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
  11414. if (!props) {
  11415. return;
  11416. }
  11417. nsresult rv = props->GetPropertyAsInterface(
  11418. NS_LITERAL_STRING("docshell.previousURI"),
  11419. NS_GET_IID(nsIURI),
  11420. reinterpret_cast<void**>(aURI));
  11421. if (NS_FAILED(rv)) {
  11422. // There is no last visit for this channel, so this must be the first
  11423. // link. Link the visit to the referrer of this request, if any.
  11424. // Treat referrer as null if there is an error getting it.
  11425. (void)NS_GetReferrerFromChannel(aChannel, aURI);
  11426. } else {
  11427. rv = props->GetPropertyAsUint32(NS_LITERAL_STRING("docshell.previousFlags"),
  11428. aChannelRedirectFlags);
  11429. NS_WARNING_ASSERTION(
  11430. NS_SUCCEEDED(rv),
  11431. "Could not fetch previous flags, URI will be treated like referrer");
  11432. }
  11433. }
  11434. void
  11435. nsDocShell::SaveLastVisit(nsIChannel* aChannel,
  11436. nsIURI* aURI,
  11437. uint32_t aChannelRedirectFlags)
  11438. {
  11439. nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
  11440. if (!props || !aURI) {
  11441. return;
  11442. }
  11443. props->SetPropertyAsInterface(NS_LITERAL_STRING("docshell.previousURI"),
  11444. aURI);
  11445. props->SetPropertyAsUint32(NS_LITERAL_STRING("docshell.previousFlags"),
  11446. aChannelRedirectFlags);
  11447. }
  11448. void
  11449. nsDocShell::AddURIVisit(nsIURI* aURI,
  11450. nsIURI* aReferrerURI,
  11451. nsIURI* aPreviousURI,
  11452. uint32_t aChannelRedirectFlags,
  11453. uint32_t aResponseStatus)
  11454. {
  11455. MOZ_ASSERT(aURI, "Visited URI is null!");
  11456. MOZ_ASSERT(mLoadType != LOAD_ERROR_PAGE &&
  11457. mLoadType != LOAD_BYPASS_HISTORY,
  11458. "Do not add error or bypass pages to global history");
  11459. // Only content-type docshells save URI visits. Also don't do
  11460. // anything here if we're not supposed to use global history.
  11461. if (mItemType != typeContent || !mUseGlobalHistory || UsePrivateBrowsing()) {
  11462. return;
  11463. }
  11464. nsCOMPtr<IHistory> history = services::GetHistoryService();
  11465. if (history) {
  11466. uint32_t visitURIFlags = 0;
  11467. if (!IsFrame()) {
  11468. visitURIFlags |= IHistory::TOP_LEVEL;
  11469. }
  11470. if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) {
  11471. visitURIFlags |= IHistory::REDIRECT_TEMPORARY;
  11472. } else if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_PERMANENT) {
  11473. visitURIFlags |= IHistory::REDIRECT_PERMANENT;
  11474. }
  11475. if (aResponseStatus >= 300 && aResponseStatus < 400) {
  11476. visitURIFlags |= IHistory::REDIRECT_SOURCE;
  11477. }
  11478. // Errors 400-501 and 505 are considered unrecoverable, in the sense a
  11479. // simple retry attempt by the user is unlikely to solve them.
  11480. // 408 is special cased, since may actually indicate a temporary
  11481. // connection problem.
  11482. else if (aResponseStatus != 408 &&
  11483. ((aResponseStatus >= 400 && aResponseStatus <= 501) ||
  11484. aResponseStatus == 505)) {
  11485. visitURIFlags |= IHistory::UNRECOVERABLE_ERROR;
  11486. }
  11487. (void)history->VisitURI(aURI, aPreviousURI, visitURIFlags);
  11488. } else if (mGlobalHistory) {
  11489. // Falls back to sync global history interface.
  11490. (void)mGlobalHistory->AddURI(aURI,
  11491. !!aChannelRedirectFlags,
  11492. !IsFrame(),
  11493. aReferrerURI);
  11494. }
  11495. }
  11496. //*****************************************************************************
  11497. // nsDocShell: Helper Routines
  11498. //*****************************************************************************
  11499. NS_IMETHODIMP
  11500. nsDocShell::SetLoadType(uint32_t aLoadType)
  11501. {
  11502. mLoadType = aLoadType;
  11503. return NS_OK;
  11504. }
  11505. NS_IMETHODIMP
  11506. nsDocShell::GetLoadType(uint32_t* aLoadType)
  11507. {
  11508. *aLoadType = mLoadType;
  11509. return NS_OK;
  11510. }
  11511. nsresult
  11512. nsDocShell::ConfirmRepost(bool* aRepost)
  11513. {
  11514. nsCOMPtr<nsIPrompt> prompter;
  11515. CallGetInterface(this, static_cast<nsIPrompt**>(getter_AddRefs(prompter)));
  11516. if (!prompter) {
  11517. return NS_ERROR_NOT_AVAILABLE;
  11518. }
  11519. nsCOMPtr<nsIStringBundleService> stringBundleService =
  11520. mozilla::services::GetStringBundleService();
  11521. if (!stringBundleService) {
  11522. return NS_ERROR_FAILURE;
  11523. }
  11524. nsCOMPtr<nsIStringBundle> appBundle;
  11525. nsresult rv = stringBundleService->CreateBundle(kAppstringsBundleURL,
  11526. getter_AddRefs(appBundle));
  11527. NS_ENSURE_SUCCESS(rv, rv);
  11528. nsCOMPtr<nsIStringBundle> brandBundle;
  11529. rv = stringBundleService->CreateBundle(kBrandBundleURL,
  11530. getter_AddRefs(brandBundle));
  11531. NS_ENSURE_SUCCESS(rv, rv);
  11532. NS_ASSERTION(prompter && brandBundle && appBundle,
  11533. "Unable to set up repost prompter.");
  11534. nsXPIDLString brandName;
  11535. rv = brandBundle->GetStringFromName(u"brandShortName",
  11536. getter_Copies(brandName));
  11537. nsXPIDLString msgString, button0Title;
  11538. if (NS_FAILED(rv)) { // No brand, use the generic version.
  11539. rv = appBundle->GetStringFromName(u"confirmRepostPrompt",
  11540. getter_Copies(msgString));
  11541. } else {
  11542. // Brand available - if the app has an override file with formatting, the
  11543. // app name will be included. Without an override, the prompt will look
  11544. // like the generic version.
  11545. const char16_t* formatStrings[] = { brandName.get() };
  11546. rv = appBundle->FormatStringFromName(u"confirmRepostPrompt",
  11547. formatStrings,
  11548. ArrayLength(formatStrings),
  11549. getter_Copies(msgString));
  11550. }
  11551. if (NS_FAILED(rv)) {
  11552. return rv;
  11553. }
  11554. rv = appBundle->GetStringFromName(u"resendButton.label",
  11555. getter_Copies(button0Title));
  11556. if (NS_FAILED(rv)) {
  11557. return rv;
  11558. }
  11559. int32_t buttonPressed;
  11560. // The actual value here is irrelevant, but we can't pass an invalid
  11561. // bool through XPConnect.
  11562. bool checkState = false;
  11563. rv = prompter->ConfirmEx(
  11564. nullptr, msgString.get(),
  11565. (nsIPrompt::BUTTON_POS_0 * nsIPrompt::BUTTON_TITLE_IS_STRING) +
  11566. (nsIPrompt::BUTTON_POS_1 * nsIPrompt::BUTTON_TITLE_CANCEL),
  11567. button0Title.get(), nullptr, nullptr, nullptr, &checkState, &buttonPressed);
  11568. if (NS_FAILED(rv)) {
  11569. return rv;
  11570. }
  11571. *aRepost = (buttonPressed == 0);
  11572. return NS_OK;
  11573. }
  11574. NS_IMETHODIMP
  11575. nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt,
  11576. nsIStringBundle** aStringBundle)
  11577. {
  11578. NS_ENSURE_SUCCESS(GetInterface(NS_GET_IID(nsIPrompt), (void**)aPrompt),
  11579. NS_ERROR_FAILURE);
  11580. nsCOMPtr<nsIStringBundleService> stringBundleService =
  11581. mozilla::services::GetStringBundleService();
  11582. NS_ENSURE_TRUE(stringBundleService, NS_ERROR_FAILURE);
  11583. NS_ENSURE_SUCCESS(
  11584. stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle),
  11585. NS_ERROR_FAILURE);
  11586. return NS_OK;
  11587. }
  11588. NS_IMETHODIMP
  11589. nsDocShell::GetChildOffset(nsIDOMNode* aChild, nsIDOMNode* aParent,
  11590. int32_t* aOffset)
  11591. {
  11592. NS_ENSURE_ARG_POINTER(aChild || aParent);
  11593. nsCOMPtr<nsIDOMNodeList> childNodes;
  11594. NS_ENSURE_SUCCESS(aParent->GetChildNodes(getter_AddRefs(childNodes)),
  11595. NS_ERROR_FAILURE);
  11596. NS_ENSURE_TRUE(childNodes, NS_ERROR_FAILURE);
  11597. int32_t i = 0;
  11598. for (; true; i++) {
  11599. nsCOMPtr<nsIDOMNode> childNode;
  11600. NS_ENSURE_SUCCESS(childNodes->Item(i, getter_AddRefs(childNode)),
  11601. NS_ERROR_FAILURE);
  11602. NS_ENSURE_TRUE(childNode, NS_ERROR_FAILURE);
  11603. if (childNode.get() == aChild) {
  11604. *aOffset = i;
  11605. return NS_OK;
  11606. }
  11607. }
  11608. return NS_ERROR_FAILURE;
  11609. }
  11610. nsIScrollableFrame*
  11611. nsDocShell::GetRootScrollFrame()
  11612. {
  11613. nsCOMPtr<nsIPresShell> shell = GetPresShell();
  11614. NS_ENSURE_TRUE(shell, nullptr);
  11615. return shell->GetRootScrollFrameAsScrollableExternal();
  11616. }
  11617. NS_IMETHODIMP
  11618. nsDocShell::EnsureScriptEnvironment()
  11619. {
  11620. if (mScriptGlobal) {
  11621. return NS_OK;
  11622. }
  11623. if (mIsBeingDestroyed) {
  11624. return NS_ERROR_NOT_AVAILABLE;
  11625. }
  11626. #ifdef DEBUG
  11627. NS_ASSERTION(!mInEnsureScriptEnv,
  11628. "Infinite loop! Calling EnsureScriptEnvironment() from "
  11629. "within EnsureScriptEnvironment()!");
  11630. // Yeah, this isn't re-entrant safe, but that's ok since if we
  11631. // re-enter this method, we'll infinitely loop...
  11632. AutoRestore<bool> boolSetter(mInEnsureScriptEnv);
  11633. mInEnsureScriptEnv = true;
  11634. #endif
  11635. nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
  11636. NS_ENSURE_TRUE(browserChrome, NS_ERROR_NOT_AVAILABLE);
  11637. uint32_t chromeFlags;
  11638. browserChrome->GetChromeFlags(&chromeFlags);
  11639. // If our window is modal and we're not opened as chrome, make
  11640. // this window a modal content window.
  11641. mScriptGlobal = NS_NewScriptGlobalObject(mItemType == typeChrome);
  11642. MOZ_ASSERT(mScriptGlobal);
  11643. mScriptGlobal->SetDocShell(this);
  11644. // Ensure the script object is set up to run script.
  11645. return mScriptGlobal->EnsureScriptEnvironment();
  11646. }
  11647. NS_IMETHODIMP
  11648. nsDocShell::EnsureEditorData()
  11649. {
  11650. bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor();
  11651. if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) {
  11652. // We shouldn't recreate the editor data if it already exists, or
  11653. // we're shutting down, or we already have a detached editor data
  11654. // stored in the session history. We should only have one editordata
  11655. // per docshell.
  11656. mEditorData = new nsDocShellEditorData(this);
  11657. }
  11658. return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE;
  11659. }
  11660. nsresult
  11661. nsDocShell::EnsureTransferableHookData()
  11662. {
  11663. if (!mTransferableHookData) {
  11664. mTransferableHookData = new nsTransferableHookData();
  11665. }
  11666. return NS_OK;
  11667. }
  11668. NS_IMETHODIMP
  11669. nsDocShell::EnsureFind()
  11670. {
  11671. nsresult rv;
  11672. if (!mFind) {
  11673. mFind = do_CreateInstance("@mozilla.org/embedcomp/find;1", &rv);
  11674. if (NS_FAILED(rv)) {
  11675. return rv;
  11676. }
  11677. }
  11678. // we promise that the nsIWebBrowserFind that we return has been set
  11679. // up to point to the focused, or content window, so we have to
  11680. // set that up each time.
  11681. nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject();
  11682. NS_ENSURE_TRUE(scriptGO, NS_ERROR_UNEXPECTED);
  11683. // default to our window
  11684. nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO);
  11685. nsCOMPtr<nsPIDOMWindowOuter> windowToSearch;
  11686. nsFocusManager::GetFocusedDescendant(ourWindow, true,
  11687. getter_AddRefs(windowToSearch));
  11688. nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind);
  11689. if (!findInFrames) {
  11690. return NS_ERROR_NO_INTERFACE;
  11691. }
  11692. rv = findInFrames->SetRootSearchFrame(ourWindow);
  11693. if (NS_FAILED(rv)) {
  11694. return rv;
  11695. }
  11696. rv = findInFrames->SetCurrentSearchFrame(windowToSearch);
  11697. if (NS_FAILED(rv)) {
  11698. return rv;
  11699. }
  11700. return NS_OK;
  11701. }
  11702. bool
  11703. nsDocShell::IsFrame()
  11704. {
  11705. nsCOMPtr<nsIDocShellTreeItem> parent;
  11706. GetSameTypeParent(getter_AddRefs(parent));
  11707. return !!parent;
  11708. }
  11709. NS_IMETHODIMP
  11710. nsDocShell::IsBeingDestroyed(bool* aDoomed)
  11711. {
  11712. NS_ENSURE_ARG(aDoomed);
  11713. *aDoomed = mIsBeingDestroyed;
  11714. return NS_OK;
  11715. }
  11716. NS_IMETHODIMP
  11717. nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult)
  11718. {
  11719. NS_ENSURE_ARG(aResult);
  11720. *aResult = mIsExecutingOnLoadHandler;
  11721. return NS_OK;
  11722. }
  11723. NS_IMETHODIMP
  11724. nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState)
  11725. {
  11726. if (mOSHE) {
  11727. mOSHE->GetLayoutHistoryState(aLayoutHistoryState);
  11728. }
  11729. return NS_OK;
  11730. }
  11731. NS_IMETHODIMP
  11732. nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState)
  11733. {
  11734. if (mOSHE) {
  11735. mOSHE->SetLayoutHistoryState(aLayoutHistoryState);
  11736. }
  11737. return NS_OK;
  11738. }
  11739. nsRefreshTimer::nsRefreshTimer()
  11740. : mDelay(0), mRepeat(false), mMetaRefresh(false)
  11741. {
  11742. }
  11743. nsRefreshTimer::~nsRefreshTimer()
  11744. {
  11745. }
  11746. NS_IMPL_ADDREF(nsRefreshTimer)
  11747. NS_IMPL_RELEASE(nsRefreshTimer)
  11748. NS_INTERFACE_MAP_BEGIN(nsRefreshTimer)
  11749. NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITimerCallback)
  11750. NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
  11751. NS_INTERFACE_MAP_END_THREADSAFE
  11752. NS_IMETHODIMP
  11753. nsRefreshTimer::Notify(nsITimer* aTimer)
  11754. {
  11755. NS_ASSERTION(mDocShell, "DocShell is somehow null");
  11756. if (mDocShell && aTimer) {
  11757. // Get the delay count to determine load type
  11758. uint32_t delay = 0;
  11759. aTimer->GetDelay(&delay);
  11760. mDocShell->ForceRefreshURIFromTimer(mURI, delay, mMetaRefresh, aTimer, mPrincipal);
  11761. }
  11762. return NS_OK;
  11763. }
  11764. nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy(
  11765. nsIInterfaceRequestor* aRequestor)
  11766. {
  11767. if (aRequestor) {
  11768. mWeakPtr = do_GetWeakReference(aRequestor);
  11769. }
  11770. }
  11771. nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy()
  11772. {
  11773. mWeakPtr = nullptr;
  11774. }
  11775. NS_IMPL_ISUPPORTS(nsDocShell::InterfaceRequestorProxy, nsIInterfaceRequestor)
  11776. NS_IMETHODIMP
  11777. nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID,
  11778. void** aSink)
  11779. {
  11780. NS_ENSURE_ARG_POINTER(aSink);
  11781. nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr);
  11782. if (ifReq) {
  11783. return ifReq->GetInterface(aIID, aSink);
  11784. }
  11785. *aSink = nullptr;
  11786. return NS_NOINTERFACE;
  11787. }
  11788. nsresult
  11789. nsDocShell::SetBaseUrlForWyciwyg(nsIContentViewer* aContentViewer)
  11790. {
  11791. if (!aContentViewer) {
  11792. return NS_ERROR_FAILURE;
  11793. }
  11794. nsCOMPtr<nsIURI> baseURI;
  11795. nsresult rv = NS_ERROR_NOT_AVAILABLE;
  11796. if (sURIFixup) {
  11797. rv = sURIFixup->CreateExposableURI(mCurrentURI, getter_AddRefs(baseURI));
  11798. }
  11799. // Get the current document and set the base uri
  11800. if (baseURI) {
  11801. nsIDocument* document = aContentViewer->GetDocument();
  11802. if (document) {
  11803. document->SetBaseURI(baseURI);
  11804. }
  11805. }
  11806. return rv;
  11807. }
  11808. //*****************************************************************************
  11809. // nsDocShell::nsIAuthPromptProvider
  11810. //*****************************************************************************
  11811. NS_IMETHODIMP
  11812. nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID,
  11813. void** aResult)
  11814. {
  11815. // a priority prompt request will override a false mAllowAuth setting
  11816. bool priorityPrompt = (aPromptReason == PROMPT_PROXY);
  11817. if (!mAllowAuth && !priorityPrompt) {
  11818. return NS_ERROR_NOT_AVAILABLE;
  11819. }
  11820. // we're either allowing auth, or it's a proxy request
  11821. nsresult rv;
  11822. nsCOMPtr<nsIPromptFactory> wwatch =
  11823. do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
  11824. NS_ENSURE_SUCCESS(rv, rv);
  11825. rv = EnsureScriptEnvironment();
  11826. NS_ENSURE_SUCCESS(rv, rv);
  11827. // Get the an auth prompter for our window so that the parenting
  11828. // of the dialogs works as it should when using tabs.
  11829. return wwatch->GetPrompt(mScriptGlobal->AsOuter(), aIID,
  11830. reinterpret_cast<void**>(aResult));
  11831. }
  11832. //*****************************************************************************
  11833. // nsDocShell::nsILoadContext
  11834. //*****************************************************************************
  11835. NS_IMETHODIMP
  11836. nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow)
  11837. {
  11838. CallGetInterface(this, aWindow);
  11839. return NS_OK;
  11840. }
  11841. NS_IMETHODIMP
  11842. nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow)
  11843. {
  11844. nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
  11845. if (win) {
  11846. win = win->GetTop();
  11847. }
  11848. win.forget(aWindow);
  11849. return NS_OK;
  11850. }
  11851. NS_IMETHODIMP
  11852. nsDocShell::GetTopFrameElement(nsIDOMElement** aElement)
  11853. {
  11854. *aElement = nullptr;
  11855. nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
  11856. if (!win) {
  11857. return NS_OK;
  11858. }
  11859. nsCOMPtr<nsPIDOMWindowOuter> top = win->GetScriptableTop();
  11860. NS_ENSURE_TRUE(top, NS_ERROR_FAILURE);
  11861. // GetFrameElementInternal, /not/ GetScriptableFrameElement -- if |top| is
  11862. // inside <iframe mozbrowser>, we want to return the iframe, not null.
  11863. // And we want to cross the content/chrome boundary.
  11864. nsCOMPtr<nsIDOMElement> elt =
  11865. do_QueryInterface(top->GetFrameElementInternal());
  11866. elt.forget(aElement);
  11867. return NS_OK;
  11868. }
  11869. NS_IMETHODIMP
  11870. nsDocShell::GetNestedFrameId(uint64_t* aId)
  11871. {
  11872. *aId = 0;
  11873. return NS_OK;
  11874. }
  11875. NS_IMETHODIMP
  11876. nsDocShell::IsTrackingProtectionOn(bool* aIsTrackingProtectionOn)
  11877. {
  11878. if (Preferences::GetBool("privacy.trackingprotection.enabled", false)) {
  11879. *aIsTrackingProtectionOn = true;
  11880. } else if (UsePrivateBrowsing() &&
  11881. Preferences::GetBool("privacy.trackingprotection.pbmode.enabled", false)) {
  11882. *aIsTrackingProtectionOn = true;
  11883. } else {
  11884. *aIsTrackingProtectionOn = false;
  11885. }
  11886. return NS_OK;
  11887. }
  11888. NS_IMETHODIMP
  11889. nsDocShell::GetIsContent(bool* aIsContent)
  11890. {
  11891. *aIsContent = (mItemType == typeContent);
  11892. return NS_OK;
  11893. }
  11894. bool
  11895. nsDocShell::IsOKToLoadURI(nsIURI* aURI)
  11896. {
  11897. NS_PRECONDITION(aURI, "Must have a URI!");
  11898. if (!mFiredUnloadEvent) {
  11899. return true;
  11900. }
  11901. if (!mLoadingURI) {
  11902. return false;
  11903. }
  11904. nsCOMPtr<nsIScriptSecurityManager> secMan =
  11905. do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
  11906. return secMan &&
  11907. NS_SUCCEEDED(secMan->CheckSameOriginURI(aURI, mLoadingURI, false));
  11908. }
  11909. //
  11910. // Routines for selection and clipboard
  11911. //
  11912. nsresult
  11913. nsDocShell::GetControllerForCommand(const char* aCommand,
  11914. nsIController** aResult)
  11915. {
  11916. NS_ENSURE_ARG_POINTER(aResult);
  11917. *aResult = nullptr;
  11918. NS_ENSURE_TRUE(mScriptGlobal, NS_ERROR_FAILURE);
  11919. nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot();
  11920. NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
  11921. return root->GetControllerForCommand(aCommand, aResult);
  11922. }
  11923. NS_IMETHODIMP
  11924. nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult)
  11925. {
  11926. NS_ENSURE_ARG_POINTER(aResult);
  11927. *aResult = false;
  11928. nsresult rv = NS_ERROR_FAILURE;
  11929. nsCOMPtr<nsIController> controller;
  11930. rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
  11931. if (controller) {
  11932. rv = controller->IsCommandEnabled(aCommand, aResult);
  11933. }
  11934. return rv;
  11935. }
  11936. NS_IMETHODIMP
  11937. nsDocShell::DoCommand(const char* aCommand)
  11938. {
  11939. nsresult rv = NS_ERROR_FAILURE;
  11940. nsCOMPtr<nsIController> controller;
  11941. rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
  11942. if (controller) {
  11943. rv = controller->DoCommand(aCommand);
  11944. }
  11945. return rv;
  11946. }
  11947. NS_IMETHODIMP
  11948. nsDocShell::DoCommandWithParams(const char* aCommand, nsICommandParams* aParams)
  11949. {
  11950. nsCOMPtr<nsIController> controller;
  11951. nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
  11952. if (NS_WARN_IF(NS_FAILED(rv))) {
  11953. return rv;
  11954. }
  11955. nsCOMPtr<nsICommandController> commandController =
  11956. do_QueryInterface(controller, &rv);
  11957. if (NS_WARN_IF(NS_FAILED(rv))) {
  11958. return rv;
  11959. }
  11960. return commandController->DoCommandWithParams(aCommand, aParams);
  11961. }
  11962. nsresult
  11963. nsDocShell::EnsureCommandHandler()
  11964. {
  11965. if (!mCommandManager) {
  11966. nsCOMPtr<nsPICommandUpdater> commandUpdater =
  11967. do_CreateInstance("@mozilla.org/embedcomp/command-manager;1");
  11968. if (!commandUpdater) {
  11969. return NS_ERROR_OUT_OF_MEMORY;
  11970. }
  11971. nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow();
  11972. nsresult rv = commandUpdater->Init(domWindow);
  11973. if (NS_SUCCEEDED(rv)) {
  11974. mCommandManager = do_QueryInterface(commandUpdater);
  11975. }
  11976. }
  11977. return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
  11978. }
  11979. NS_IMETHODIMP
  11980. nsDocShell::CanCutSelection(bool* aResult)
  11981. {
  11982. return IsCommandEnabled("cmd_cut", aResult);
  11983. }
  11984. NS_IMETHODIMP
  11985. nsDocShell::CanCopySelection(bool* aResult)
  11986. {
  11987. return IsCommandEnabled("cmd_copy", aResult);
  11988. }
  11989. NS_IMETHODIMP
  11990. nsDocShell::CanCopyLinkLocation(bool* aResult)
  11991. {
  11992. return IsCommandEnabled("cmd_copyLink", aResult);
  11993. }
  11994. NS_IMETHODIMP
  11995. nsDocShell::CanCopyImageLocation(bool* aResult)
  11996. {
  11997. return IsCommandEnabled("cmd_copyImageLocation", aResult);
  11998. }
  11999. NS_IMETHODIMP
  12000. nsDocShell::CanCopyImageContents(bool* aResult)
  12001. {
  12002. return IsCommandEnabled("cmd_copyImageContents", aResult);
  12003. }
  12004. NS_IMETHODIMP
  12005. nsDocShell::CanPaste(bool* aResult)
  12006. {
  12007. return IsCommandEnabled("cmd_paste", aResult);
  12008. }
  12009. NS_IMETHODIMP
  12010. nsDocShell::CutSelection(void)
  12011. {
  12012. return DoCommand("cmd_cut");
  12013. }
  12014. NS_IMETHODIMP
  12015. nsDocShell::CopySelection(void)
  12016. {
  12017. return DoCommand("cmd_copy");
  12018. }
  12019. NS_IMETHODIMP
  12020. nsDocShell::CopyLinkLocation(void)
  12021. {
  12022. return DoCommand("cmd_copyLink");
  12023. }
  12024. NS_IMETHODIMP
  12025. nsDocShell::CopyImageLocation(void)
  12026. {
  12027. return DoCommand("cmd_copyImageLocation");
  12028. }
  12029. NS_IMETHODIMP
  12030. nsDocShell::CopyImageContents(void)
  12031. {
  12032. return DoCommand("cmd_copyImageContents");
  12033. }
  12034. NS_IMETHODIMP
  12035. nsDocShell::Paste(void)
  12036. {
  12037. return DoCommand("cmd_paste");
  12038. }
  12039. NS_IMETHODIMP
  12040. nsDocShell::SelectAll(void)
  12041. {
  12042. return DoCommand("cmd_selectAll");
  12043. }
  12044. //
  12045. // SelectNone
  12046. //
  12047. // Collapses the current selection, insertion point ends up at beginning
  12048. // of previous selection.
  12049. //
  12050. NS_IMETHODIMP
  12051. nsDocShell::SelectNone(void)
  12052. {
  12053. return DoCommand("cmd_selectNone");
  12054. }
  12055. // link handling
  12056. class OnLinkClickEvent : public Runnable
  12057. {
  12058. public:
  12059. OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
  12060. nsIURI* aURI,
  12061. const char16_t* aTargetSpec,
  12062. const nsAString& aFileName,
  12063. nsIInputStream* aPostDataStream,
  12064. nsIInputStream* aHeadersDataStream,
  12065. bool aIsTrusted,
  12066. nsIPrincipal* aTriggeringPrincipal);
  12067. NS_IMETHOD Run() override
  12068. {
  12069. nsAutoPopupStatePusher popupStatePusher(mPopupState);
  12070. // We need to set up an AutoJSAPI here for the following reason: When we do
  12071. // OnLinkClickSync we'll eventually end up in nsGlobalWindow::OpenInternal
  12072. // which only does popup blocking if !LegacyIsCallerChromeOrNativeCode().
  12073. // So we need to fake things so that we don't look like native code as far
  12074. // as LegacyIsCallerNativeCode() is concerned.
  12075. AutoJSAPI jsapi;
  12076. if (mIsTrusted || jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) {
  12077. mHandler->OnLinkClickSync(mContent, mURI,
  12078. mTargetSpec.get(), mFileName,
  12079. mPostDataStream, mHeadersDataStream,
  12080. nullptr, nullptr, mTriggeringPrincipal);
  12081. }
  12082. return NS_OK;
  12083. }
  12084. private:
  12085. RefPtr<nsDocShell> mHandler;
  12086. nsCOMPtr<nsIURI> mURI;
  12087. nsString mTargetSpec;
  12088. nsString mFileName;
  12089. nsCOMPtr<nsIInputStream> mPostDataStream;
  12090. nsCOMPtr<nsIInputStream> mHeadersDataStream;
  12091. nsCOMPtr<nsIContent> mContent;
  12092. PopupControlState mPopupState;
  12093. bool mIsTrusted;
  12094. nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
  12095. };
  12096. OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
  12097. nsIContent* aContent,
  12098. nsIURI* aURI,
  12099. const char16_t* aTargetSpec,
  12100. const nsAString& aFileName,
  12101. nsIInputStream* aPostDataStream,
  12102. nsIInputStream* aHeadersDataStream,
  12103. bool aIsTrusted,
  12104. nsIPrincipal* aTriggeringPrincipal)
  12105. : mHandler(aHandler)
  12106. , mURI(aURI)
  12107. , mTargetSpec(aTargetSpec)
  12108. , mFileName(aFileName)
  12109. , mPostDataStream(aPostDataStream)
  12110. , mHeadersDataStream(aHeadersDataStream)
  12111. , mContent(aContent)
  12112. , mPopupState(mHandler->mScriptGlobal->GetPopupControlState())
  12113. , mIsTrusted(aIsTrusted)
  12114. , mTriggeringPrincipal(aTriggeringPrincipal)
  12115. {
  12116. }
  12117. NS_IMETHODIMP
  12118. nsDocShell::OnLinkClick(nsIContent* aContent,
  12119. nsIURI* aURI,
  12120. const char16_t* aTargetSpec,
  12121. const nsAString& aFileName,
  12122. nsIInputStream* aPostDataStream,
  12123. nsIInputStream* aHeadersDataStream,
  12124. bool aIsTrusted,
  12125. nsIPrincipal* aTriggeringPrincipal)
  12126. {
  12127. NS_ASSERTION(NS_IsMainThread(), "wrong thread");
  12128. if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) {
  12129. return NS_OK;
  12130. }
  12131. // On history navigation through Back/Forward buttons, don't execute
  12132. // automatic JavaScript redirection such as |anchorElement.click()| or
  12133. // |formElement.submit()|.
  12134. //
  12135. // XXX |formElement.submit()| bypasses this checkpoint because it calls
  12136. // nsDocShell::OnLinkClickSync(...) instead.
  12137. if (ShouldBlockLoadingForBackButton()) {
  12138. return NS_OK;
  12139. }
  12140. if (aContent->IsEditable()) {
  12141. return NS_OK;
  12142. }
  12143. nsresult rv = NS_ERROR_FAILURE;
  12144. nsAutoString target;
  12145. nsCOMPtr<nsIWebBrowserChrome3> browserChrome3 = do_GetInterface(mTreeOwner);
  12146. if (browserChrome3) {
  12147. nsCOMPtr<nsIDOMNode> linkNode = do_QueryInterface(aContent);
  12148. nsAutoString oldTarget(aTargetSpec);
  12149. rv = browserChrome3->OnBeforeLinkTraversal(oldTarget, aURI,
  12150. linkNode, mIsAppTab, target);
  12151. }
  12152. if (NS_FAILED(rv)) {
  12153. target = aTargetSpec;
  12154. }
  12155. nsCOMPtr<nsIRunnable> ev =
  12156. new OnLinkClickEvent(this, aContent, aURI, target.get(), aFileName,
  12157. aPostDataStream, aHeadersDataStream,
  12158. aIsTrusted, aTriggeringPrincipal);
  12159. return NS_DispatchToCurrentThread(ev);
  12160. }
  12161. NS_IMETHODIMP
  12162. nsDocShell::OnLinkClickSync(nsIContent* aContent,
  12163. nsIURI* aURI,
  12164. const char16_t* aTargetSpec,
  12165. const nsAString& aFileName,
  12166. nsIInputStream* aPostDataStream,
  12167. nsIInputStream* aHeadersDataStream,
  12168. nsIDocShell** aDocShell,
  12169. nsIRequest** aRequest,
  12170. nsIPrincipal* aTriggeringPrincipal)
  12171. {
  12172. // Initialize the DocShell / Request
  12173. if (aDocShell) {
  12174. *aDocShell = nullptr;
  12175. }
  12176. if (aRequest) {
  12177. *aRequest = nullptr;
  12178. }
  12179. if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) {
  12180. return NS_OK;
  12181. }
  12182. // XXX When the linking node was HTMLFormElement, it is synchronous event.
  12183. // That is, the caller of this method is not |OnLinkClickEvent::Run()|
  12184. // but |HTMLFormElement::SubmitSubmission(...)|.
  12185. if (aContent->IsHTMLElement(nsGkAtoms::form) &&
  12186. ShouldBlockLoadingForBackButton()) {
  12187. return NS_OK;
  12188. }
  12189. if (aContent->IsEditable()) {
  12190. return NS_OK;
  12191. }
  12192. {
  12193. // defer to an external protocol handler if necessary...
  12194. nsCOMPtr<nsIExternalProtocolService> extProtService =
  12195. do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID);
  12196. if (extProtService) {
  12197. nsAutoCString scheme;
  12198. aURI->GetScheme(scheme);
  12199. if (!scheme.IsEmpty()) {
  12200. // if the URL scheme does not correspond to an exposed protocol, then we
  12201. // need to hand this link click over to the external protocol handler.
  12202. bool isExposed;
  12203. nsresult rv =
  12204. extProtService->IsExposedProtocol(scheme.get(), &isExposed);
  12205. if (NS_SUCCEEDED(rv) && !isExposed) {
  12206. return extProtService->LoadURI(aURI, this);
  12207. }
  12208. }
  12209. }
  12210. }
  12211. uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
  12212. if (IsElementAnchor(aContent)) {
  12213. MOZ_ASSERT(aContent->IsHTMLElement());
  12214. nsAutoString referrer;
  12215. aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, referrer);
  12216. nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(referrer);
  12217. while (tok.hasMoreTokens()) {
  12218. const nsAString& token = tok.nextToken();
  12219. if (token.LowerCaseEqualsLiteral("noreferrer")) {
  12220. flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
  12221. INTERNAL_LOAD_FLAGS_NO_OPENER;
  12222. // We now have all the flags we could possibly have, so just stop.
  12223. break;
  12224. }
  12225. if (token.LowerCaseEqualsLiteral("noopener")) {
  12226. flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
  12227. }
  12228. }
  12229. }
  12230. // Get the owner document of the link that was clicked, this will be
  12231. // the document that the link is in, or the last document that the
  12232. // link was in. From that document, we'll get the URI to use as the
  12233. // referer, since the current URI in this docshell may be a
  12234. // new document that we're in the process of loading.
  12235. nsCOMPtr<nsIDocument> refererDoc = aContent->OwnerDoc();
  12236. NS_ENSURE_TRUE(refererDoc, NS_ERROR_UNEXPECTED);
  12237. // Now check that the refererDoc's inner window is the current inner
  12238. // window for mScriptGlobal. If it's not, then we don't want to
  12239. // follow this link.
  12240. nsPIDOMWindowInner* refererInner = refererDoc->GetInnerWindow();
  12241. NS_ENSURE_TRUE(refererInner, NS_ERROR_UNEXPECTED);
  12242. if (!mScriptGlobal ||
  12243. mScriptGlobal->AsOuter()->GetCurrentInnerWindow() != refererInner) {
  12244. // We're no longer the current inner window
  12245. return NS_OK;
  12246. }
  12247. nsCOMPtr<nsIURI> referer = refererDoc->GetDocumentURI();
  12248. uint32_t refererPolicy = refererDoc->GetReferrerPolicy();
  12249. // get referrer attribute from clicked link and parse it
  12250. // if per element referrer is enabled, the element referrer overrules
  12251. // the document wide referrer
  12252. if (IsElementAnchor(aContent)) {
  12253. net::ReferrerPolicy refPolEnum = aContent->AsElement()->GetReferrerPolicyAsEnum();
  12254. if (refPolEnum != net::RP_Unset) {
  12255. refererPolicy = refPolEnum;
  12256. }
  12257. }
  12258. // referer could be null here in some odd cases, but that's ok,
  12259. // we'll just load the link w/o sending a referer in those cases.
  12260. nsAutoString target(aTargetSpec);
  12261. // If this is an anchor element, grab its type property to use as a hint
  12262. nsAutoString typeHint;
  12263. nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(aContent));
  12264. if (anchor) {
  12265. anchor->GetType(typeHint);
  12266. NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
  12267. nsAutoCString type, dummy;
  12268. NS_ParseRequestContentType(utf8Hint, type, dummy);
  12269. CopyUTF8toUTF16(type, typeHint);
  12270. }
  12271. // Clone the URI now, in case a content policy or something messes
  12272. // with it under InternalLoad; we do _not_ want to change the URI
  12273. // our caller passed in.
  12274. nsCOMPtr<nsIURI> clonedURI;
  12275. aURI->Clone(getter_AddRefs(clonedURI));
  12276. if (!clonedURI) {
  12277. return NS_ERROR_OUT_OF_MEMORY;
  12278. }
  12279. // if the triggeringPrincipal is not passed explicitly, then we
  12280. // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
  12281. nsCOMPtr<nsIPrincipal> triggeringPrincipal =
  12282. aTriggeringPrincipal ? aTriggeringPrincipal
  12283. : aContent->NodePrincipal();
  12284. nsresult rv = InternalLoad(clonedURI, // New URI
  12285. nullptr, // Original URI
  12286. false, // LoadReplace
  12287. false, // From frame attributes
  12288. referer, // Referer URI
  12289. refererPolicy, // Referer policy
  12290. triggeringPrincipal,
  12291. aContent->NodePrincipal(),
  12292. flags,
  12293. target, // Window target
  12294. NS_LossyConvertUTF16toASCII(typeHint).get(),
  12295. aFileName, // Download as file
  12296. aPostDataStream, // Post data stream
  12297. aHeadersDataStream, // Headers stream
  12298. LOAD_LINK, // Load type
  12299. nullptr, // No SHEntry
  12300. true, // first party site
  12301. NullString(), // No srcdoc
  12302. this, // We are the source
  12303. nullptr, // baseURI not needed
  12304. aDocShell, // DocShell out-param
  12305. aRequest); // Request out-param
  12306. if (NS_SUCCEEDED(rv)) {
  12307. DispatchPings(this, aContent, aURI, referer, refererPolicy);
  12308. }
  12309. return rv;
  12310. }
  12311. NS_IMETHODIMP
  12312. nsDocShell::OnOverLink(nsIContent* aContent,
  12313. nsIURI* aURI,
  12314. const char16_t* aTargetSpec)
  12315. {
  12316. if (aContent->IsEditable()) {
  12317. return NS_OK;
  12318. }
  12319. nsCOMPtr<nsIWebBrowserChrome2> browserChrome2 = do_GetInterface(mTreeOwner);
  12320. nsresult rv = NS_ERROR_FAILURE;
  12321. nsCOMPtr<nsIWebBrowserChrome> browserChrome;
  12322. if (!browserChrome2) {
  12323. browserChrome = do_GetInterface(mTreeOwner);
  12324. if (!browserChrome) {
  12325. return rv;
  12326. }
  12327. }
  12328. nsCOMPtr<nsITextToSubURI> textToSubURI =
  12329. do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
  12330. if (NS_FAILED(rv)) {
  12331. return rv;
  12332. }
  12333. // use url origin charset to unescape the URL
  12334. nsAutoCString charset;
  12335. rv = aURI->GetOriginCharset(charset);
  12336. NS_ENSURE_SUCCESS(rv, rv);
  12337. nsAutoCString spec;
  12338. rv = aURI->GetSpec(spec);
  12339. NS_ENSURE_SUCCESS(rv, rv);
  12340. nsAutoString uStr;
  12341. rv = textToSubURI->UnEscapeURIForUI(charset, spec, uStr);
  12342. NS_ENSURE_SUCCESS(rv, rv);
  12343. mozilla::net::PredictorPredict(aURI, mCurrentURI,
  12344. nsINetworkPredictor::PREDICT_LINK,
  12345. this, nullptr);
  12346. if (browserChrome2) {
  12347. nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aContent);
  12348. rv = browserChrome2->SetStatusWithContext(nsIWebBrowserChrome::STATUS_LINK,
  12349. uStr, element);
  12350. } else {
  12351. rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_LINK, uStr.get());
  12352. }
  12353. return rv;
  12354. }
  12355. NS_IMETHODIMP
  12356. nsDocShell::OnLeaveLink()
  12357. {
  12358. nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
  12359. nsresult rv = NS_ERROR_FAILURE;
  12360. if (browserChrome) {
  12361. rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_LINK,
  12362. EmptyString().get());
  12363. }
  12364. return rv;
  12365. }
  12366. bool
  12367. nsDocShell::ShouldBlockLoadingForBackButton()
  12368. {
  12369. if (!(mLoadType & LOAD_CMD_HISTORY) ||
  12370. EventStateManager::IsHandlingUserInput() ||
  12371. !Preferences::GetBool("accessibility.blockjsredirection")) {
  12372. return false;
  12373. }
  12374. bool canGoForward = false;
  12375. GetCanGoForward(&canGoForward);
  12376. return canGoForward;
  12377. }
  12378. bool
  12379. nsDocShell::PluginsAllowedInCurrentDoc()
  12380. {
  12381. bool pluginsAllowed = false;
  12382. if (!mContentViewer) {
  12383. return false;
  12384. }
  12385. nsIDocument* doc = mContentViewer->GetDocument();
  12386. if (!doc) {
  12387. return false;
  12388. }
  12389. doc->GetAllowPlugins(&pluginsAllowed);
  12390. return pluginsAllowed;
  12391. }
  12392. //----------------------------------------------------------------------
  12393. // Web Shell Services API
  12394. // This functions is only called when a new charset is detected in loading a
  12395. // document. Its name should be changed to "CharsetReloadDocument"
  12396. NS_IMETHODIMP
  12397. nsDocShell::ReloadDocument(const char* aCharset, int32_t aSource)
  12398. {
  12399. // XXX hack. keep the aCharset and aSource wait to pick it up
  12400. nsCOMPtr<nsIContentViewer> cv;
  12401. NS_ENSURE_SUCCESS(GetContentViewer(getter_AddRefs(cv)), NS_ERROR_FAILURE);
  12402. if (cv) {
  12403. int32_t hint;
  12404. cv->GetHintCharacterSetSource(&hint);
  12405. if (aSource > hint) {
  12406. nsCString charset(aCharset);
  12407. cv->SetHintCharacterSet(charset);
  12408. cv->SetHintCharacterSetSource(aSource);
  12409. if (eCharsetReloadRequested != mCharsetReloadState) {
  12410. mCharsetReloadState = eCharsetReloadRequested;
  12411. return Reload(LOAD_FLAGS_CHARSET_CHANGE);
  12412. }
  12413. }
  12414. }
  12415. // return failure if this request is not accepted due to mCharsetReloadState
  12416. return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
  12417. }
  12418. NS_IMETHODIMP
  12419. nsDocShell::StopDocumentLoad(void)
  12420. {
  12421. if (eCharsetReloadRequested != mCharsetReloadState) {
  12422. Stop(nsIWebNavigation::STOP_ALL);
  12423. return NS_OK;
  12424. }
  12425. // return failer if this request is not accepted due to mCharsetReloadState
  12426. return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
  12427. }
  12428. NS_IMETHODIMP
  12429. nsDocShell::GetPrintPreview(nsIWebBrowserPrint** aPrintPreview)
  12430. {
  12431. *aPrintPreview = nullptr;
  12432. #if NS_PRINT_PREVIEW
  12433. nsCOMPtr<nsIDocumentViewerPrint> print = do_QueryInterface(mContentViewer);
  12434. if (!print || !print->IsInitializedForPrintPreview()) {
  12435. Stop(nsIWebNavigation::STOP_ALL);
  12436. nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::CreateWithInheritedAttributes(this);
  12437. nsresult rv = CreateAboutBlankContentViewer(principal, nullptr);
  12438. NS_ENSURE_SUCCESS(rv, rv);
  12439. print = do_QueryInterface(mContentViewer);
  12440. NS_ENSURE_STATE(print);
  12441. print->InitializeForPrintPreview();
  12442. }
  12443. nsCOMPtr<nsIWebBrowserPrint> result = do_QueryInterface(print);
  12444. result.forget(aPrintPreview);
  12445. return NS_OK;
  12446. #else
  12447. return NS_ERROR_NOT_IMPLEMENTED;
  12448. #endif
  12449. }
  12450. #ifdef DEBUG
  12451. unsigned long nsDocShell::gNumberOfDocShells = 0;
  12452. #endif
  12453. NS_IMETHODIMP
  12454. nsDocShell::GetCanExecuteScripts(bool* aResult)
  12455. {
  12456. *aResult = mCanExecuteScripts;
  12457. return NS_OK;
  12458. }
  12459. /* [infallible] */ NS_IMETHODIMP
  12460. nsDocShell::SetFrameType(uint32_t aFrameType)
  12461. {
  12462. mFrameType = aFrameType;
  12463. return NS_OK;
  12464. }
  12465. /* [infallible] */ NS_IMETHODIMP
  12466. nsDocShell::GetFrameType(uint32_t* aFrameType)
  12467. {
  12468. *aFrameType = mFrameType;
  12469. return NS_OK;
  12470. }
  12471. /* [infallible] */ NS_IMETHODIMP
  12472. nsDocShell::GetIsApp(bool* aIsApp)
  12473. {
  12474. *aIsApp = (mFrameType == FRAME_TYPE_APP);
  12475. return NS_OK;
  12476. }
  12477. /* [infallible] */ NS_IMETHODIMP
  12478. nsDocShell::GetIsMozBrowserOrApp(bool* aIsMozBrowserOrApp)
  12479. {
  12480. *aIsMozBrowserOrApp = (mFrameType != FRAME_TYPE_REGULAR);
  12481. return NS_OK;
  12482. }
  12483. uint32_t
  12484. nsDocShell::GetInheritedFrameType()
  12485. {
  12486. if (mFrameType != FRAME_TYPE_REGULAR) {
  12487. return mFrameType;
  12488. }
  12489. nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
  12490. GetSameTypeParent(getter_AddRefs(parentAsItem));
  12491. nsCOMPtr<nsIDocShell> parent = do_QueryInterface(parentAsItem);
  12492. if (!parent) {
  12493. return FRAME_TYPE_REGULAR;
  12494. }
  12495. return static_cast<nsDocShell*>(parent.get())->GetInheritedFrameType();
  12496. }
  12497. /* [infallible] */ NS_IMETHODIMP
  12498. nsDocShell::GetIsIsolatedMozBrowserElement(bool* aIsIsolatedMozBrowserElement)
  12499. {
  12500. bool result = mFrameType == FRAME_TYPE_BROWSER &&
  12501. mOriginAttributes.mInIsolatedMozBrowser;
  12502. *aIsIsolatedMozBrowserElement = result;
  12503. return NS_OK;
  12504. }
  12505. /* [infallible] */ NS_IMETHODIMP
  12506. nsDocShell::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement)
  12507. {
  12508. MOZ_ASSERT(!mOriginAttributes.mInIsolatedMozBrowser ||
  12509. (GetInheritedFrameType() == FRAME_TYPE_BROWSER),
  12510. "Isolated mozbrowser should only be true inside browser frames");
  12511. bool result = (GetInheritedFrameType() == FRAME_TYPE_BROWSER) &&
  12512. mOriginAttributes.mInIsolatedMozBrowser;
  12513. *aIsInIsolatedMozBrowserElement = result;
  12514. return NS_OK;
  12515. }
  12516. /* [infallible] */ NS_IMETHODIMP
  12517. nsDocShell::GetIsInMozBrowserOrApp(bool* aIsInMozBrowserOrApp)
  12518. {
  12519. *aIsInMozBrowserOrApp = (GetInheritedFrameType() != FRAME_TYPE_REGULAR);
  12520. return NS_OK;
  12521. }
  12522. /* [infallible] */ NS_IMETHODIMP
  12523. nsDocShell::GetIsTopLevelContentDocShell(bool* aIsTopLevelContentDocShell)
  12524. {
  12525. *aIsTopLevelContentDocShell = false;
  12526. if (mItemType == typeContent) {
  12527. nsCOMPtr<nsIDocShellTreeItem> root;
  12528. GetSameTypeRootTreeItem(getter_AddRefs(root));
  12529. *aIsTopLevelContentDocShell = root.get() == static_cast<nsIDocShellTreeItem*>(this);
  12530. }
  12531. return NS_OK;
  12532. }
  12533. /* [infallible] */ NS_IMETHODIMP
  12534. nsDocShell::GetAppId(uint32_t* aAppId)
  12535. {
  12536. if (mOriginAttributes.mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
  12537. *aAppId = mOriginAttributes.mAppId;
  12538. return NS_OK;
  12539. }
  12540. nsCOMPtr<nsIDocShell> parent;
  12541. GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent));
  12542. if (!parent) {
  12543. *aAppId = nsIScriptSecurityManager::NO_APP_ID;
  12544. return NS_OK;
  12545. }
  12546. return parent->GetAppId(aAppId);
  12547. }
  12548. // Implements nsILoadContext.originAttributes
  12549. NS_IMETHODIMP
  12550. nsDocShell::GetOriginAttributes(JS::MutableHandle<JS::Value> aVal)
  12551. {
  12552. JSContext* cx = nsContentUtils::GetCurrentJSContext();
  12553. MOZ_ASSERT(cx);
  12554. return GetOriginAttributes(cx, aVal);
  12555. }
  12556. // Implements nsIDocShell.GetOriginAttributes()
  12557. NS_IMETHODIMP
  12558. nsDocShell::GetOriginAttributes(JSContext* aCx,
  12559. JS::MutableHandle<JS::Value> aVal)
  12560. {
  12561. bool ok = ToJSValue(aCx, mOriginAttributes, aVal);
  12562. NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
  12563. return NS_OK;
  12564. }
  12565. bool
  12566. nsDocShell::CanSetOriginAttributes()
  12567. {
  12568. MOZ_ASSERT(mChildList.IsEmpty());
  12569. if (!mChildList.IsEmpty()) {
  12570. return false;
  12571. }
  12572. // TODO: Bug 1273058 - mContentViewer should be null when setting origin
  12573. // attributes.
  12574. if (mContentViewer) {
  12575. nsIDocument* doc = mContentViewer->GetDocument();
  12576. if (doc) {
  12577. nsIURI* uri = doc->GetDocumentURI();
  12578. if (!uri) {
  12579. return false;
  12580. }
  12581. nsCString uriSpec = uri->GetSpecOrDefault();
  12582. MOZ_ASSERT(uriSpec.EqualsLiteral("about:blank"));
  12583. if (!uriSpec.EqualsLiteral("about:blank")) {
  12584. return false;
  12585. }
  12586. }
  12587. }
  12588. return true;
  12589. }
  12590. nsresult
  12591. nsDocShell::SetOriginAttributes(const DocShellOriginAttributes& aAttrs)
  12592. {
  12593. if (!CanSetOriginAttributes()) {
  12594. return NS_ERROR_FAILURE;
  12595. }
  12596. AssertOriginAttributesMatchPrivateBrowsing();
  12597. mOriginAttributes = aAttrs;
  12598. bool isPrivate = mOriginAttributes.mPrivateBrowsingId > 0;
  12599. // Chrome docshell can not contain OriginAttributes.mPrivateBrowsingId
  12600. if (mItemType == typeChrome && isPrivate) {
  12601. mOriginAttributes.mPrivateBrowsingId = 0;
  12602. }
  12603. SetPrivateBrowsing(isPrivate);
  12604. return NS_OK;
  12605. }
  12606. NS_IMETHODIMP
  12607. nsDocShell::SetOriginAttributesBeforeLoading(JS::Handle<JS::Value> aOriginAttributes)
  12608. {
  12609. if (!aOriginAttributes.isObject()) {
  12610. return NS_ERROR_INVALID_ARG;
  12611. }
  12612. AutoJSAPI jsapi;
  12613. if (!jsapi.Init(&aOriginAttributes.toObject())) {
  12614. return NS_ERROR_UNEXPECTED;
  12615. }
  12616. JSContext* cx = jsapi.cx();
  12617. if (NS_WARN_IF(!cx)) {
  12618. return NS_ERROR_FAILURE;
  12619. }
  12620. DocShellOriginAttributes attrs;
  12621. if (!aOriginAttributes.isObject() || !attrs.Init(cx, aOriginAttributes)) {
  12622. return NS_ERROR_INVALID_ARG;
  12623. }
  12624. return SetOriginAttributes(attrs);
  12625. }
  12626. NS_IMETHODIMP
  12627. nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes,
  12628. JSContext* aCx)
  12629. {
  12630. DocShellOriginAttributes attrs;
  12631. if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
  12632. return NS_ERROR_INVALID_ARG;
  12633. }
  12634. return SetOriginAttributes(attrs);
  12635. }
  12636. NS_IMETHODIMP
  12637. nsDocShell::GetAppManifestURL(nsAString& aAppManifestURL)
  12638. {
  12639. uint32_t appId = nsIDocShell::GetAppId();
  12640. if (appId != nsIScriptSecurityManager::NO_APP_ID &&
  12641. appId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
  12642. nsCOMPtr<nsIAppsService> appsService =
  12643. do_GetService(APPS_SERVICE_CONTRACTID);
  12644. NS_ASSERTION(appsService, "No AppsService available");
  12645. appsService->GetManifestURLByLocalId(appId, aAppManifestURL);
  12646. } else {
  12647. aAppManifestURL.SetLength(0);
  12648. }
  12649. return NS_OK;
  12650. }
  12651. NS_IMETHODIMP
  12652. nsDocShell::GetAsyncPanZoomEnabled(bool* aOut)
  12653. {
  12654. if (nsIPresShell* presShell = GetPresShell()) {
  12655. *aOut = presShell->AsyncPanZoomEnabled();
  12656. return NS_OK;
  12657. }
  12658. // If we don't have a presShell, fall back to the default platform value of
  12659. // whether or not APZ is enabled.
  12660. *aOut = gfxPlatform::AsyncPanZoomEnabled();
  12661. return NS_OK;
  12662. }
  12663. bool
  12664. nsDocShell::HasUnloadedParent()
  12665. {
  12666. RefPtr<nsDocShell> parent = GetParentDocshell();
  12667. while (parent) {
  12668. bool inUnload = false;
  12669. parent->GetIsInUnload(&inUnload);
  12670. if (inUnload) {
  12671. return true;
  12672. }
  12673. parent = parent->GetParentDocshell();
  12674. }
  12675. return false;
  12676. }
  12677. bool
  12678. nsDocShell::IsInvisible()
  12679. {
  12680. return mInvisible;
  12681. }
  12682. void
  12683. nsDocShell::SetInvisible(bool aInvisible)
  12684. {
  12685. mInvisible = aInvisible;
  12686. }
  12687. void
  12688. nsDocShell::SetOpener(nsITabParent* aOpener)
  12689. {
  12690. mOpener = do_GetWeakReference(aOpener);
  12691. }
  12692. nsITabParent*
  12693. nsDocShell::GetOpener()
  12694. {
  12695. nsCOMPtr<nsITabParent> opener(do_QueryReferent(mOpener));
  12696. return opener;
  12697. }
  12698. // The caller owns |aAsyncCause| here.
  12699. void
  12700. nsDocShell::NotifyJSRunToCompletionStart(const char* aReason,
  12701. const char16_t* aFunctionName,
  12702. const char16_t* aFilename,
  12703. const uint32_t aLineNumber,
  12704. JS::Handle<JS::Value> aAsyncStack,
  12705. const char* aAsyncCause)
  12706. {
  12707. // If first start, mark interval start.
  12708. if (mJSRunToCompletionDepth == 0) {
  12709. RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
  12710. if (timelines && timelines->HasConsumer(this)) {
  12711. timelines->AddMarkerForDocShell(this, Move(
  12712. mozilla::MakeUnique<JavascriptTimelineMarker>(
  12713. aReason, aFunctionName, aFilename, aLineNumber, MarkerTracingType::START,
  12714. aAsyncStack, aAsyncCause)));
  12715. }
  12716. }
  12717. mJSRunToCompletionDepth++;
  12718. }
  12719. void
  12720. nsDocShell::NotifyJSRunToCompletionStop()
  12721. {
  12722. mJSRunToCompletionDepth--;
  12723. // If last stop, mark interval end.
  12724. if (mJSRunToCompletionDepth == 0) {
  12725. RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
  12726. if (timelines && timelines->HasConsumer(this)) {
  12727. timelines->AddMarkerForDocShell(this, "Javascript", MarkerTracingType::END);
  12728. }
  12729. }
  12730. }
  12731. void
  12732. nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
  12733. const nsString& aKeyword)
  12734. {
  12735. if (aProvider.IsEmpty()) {
  12736. return;
  12737. }
  12738. if (XRE_IsContentProcess()) {
  12739. dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
  12740. if (contentChild) {
  12741. contentChild->SendNotifyKeywordSearchLoading(aProvider, aKeyword);
  12742. }
  12743. return;
  12744. }
  12745. #ifdef MOZ_TOOLKIT_SEARCH
  12746. nsCOMPtr<nsIBrowserSearchService> searchSvc =
  12747. do_GetService("@mozilla.org/browser/search-service;1");
  12748. if (searchSvc) {
  12749. nsCOMPtr<nsISearchEngine> searchEngine;
  12750. searchSvc->GetEngineByName(aProvider, getter_AddRefs(searchEngine));
  12751. if (searchEngine) {
  12752. nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
  12753. if (obsSvc) {
  12754. // Note that "keyword-search" refers to a search via the url
  12755. // bar, not a bookmarks keyword search.
  12756. obsSvc->NotifyObservers(searchEngine, "keyword-search", aKeyword.get());
  12757. }
  12758. }
  12759. }
  12760. #endif
  12761. }
  12762. NS_IMETHODIMP
  12763. nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNonSubresourceRequest,
  12764. bool* aShouldIntercept)
  12765. {
  12766. *aShouldIntercept = false;
  12767. // No in private browsing
  12768. if (UsePrivateBrowsing()) {
  12769. return NS_OK;
  12770. }
  12771. if (mSandboxFlags) {
  12772. // If we're sandboxed, don't intercept.
  12773. return NS_OK;
  12774. }
  12775. RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
  12776. if (!swm) {
  12777. return NS_OK;
  12778. }
  12779. nsresult result;
  12780. nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
  12781. do_GetService(THIRDPARTYUTIL_CONTRACTID, &result);
  12782. NS_ENSURE_SUCCESS(result, result);
  12783. if (mCurrentURI &&
  12784. nsContentUtils::CookiesBehavior() == nsICookieService::BEHAVIOR_REJECT_FOREIGN) {
  12785. nsAutoCString uriSpec;
  12786. if (!(mCurrentURI->GetSpecOrDefault().EqualsLiteral("about:blank"))) {
  12787. // Reject the interception of third-party iframes if the cookie behaviour
  12788. // is set to reject all third-party cookies (1). In case that this pref
  12789. // is not set or can't be read, we default to allow all cookies (0) as
  12790. // this is the default value in all.js.
  12791. bool isThirdPartyURI = true;
  12792. result = thirdPartyUtil->IsThirdPartyURI(mCurrentURI, aURI,
  12793. &isThirdPartyURI);
  12794. if (NS_FAILED(result)) {
  12795. return result;
  12796. }
  12797. if (isThirdPartyURI) {
  12798. return NS_OK;
  12799. }
  12800. }
  12801. }
  12802. if (aIsNonSubresourceRequest) {
  12803. PrincipalOriginAttributes attrs;
  12804. attrs.InheritFromDocShellToDoc(mOriginAttributes, aURI);
  12805. nsCOMPtr<nsIPrincipal> principal =
  12806. BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
  12807. *aShouldIntercept = swm->IsAvailable(principal, aURI);
  12808. return NS_OK;
  12809. }
  12810. nsCOMPtr<nsIDocument> doc = GetDocument();
  12811. if (!doc) {
  12812. return NS_ERROR_NOT_AVAILABLE;
  12813. }
  12814. ErrorResult rv;
  12815. *aShouldIntercept = swm->IsControlled(doc, rv);
  12816. if (NS_WARN_IF(rv.Failed())) {
  12817. return rv.StealNSResult();
  12818. }
  12819. return NS_OK;
  12820. }
  12821. NS_IMETHODIMP
  12822. nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
  12823. {
  12824. RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
  12825. if (!swm) {
  12826. aChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
  12827. return NS_OK;
  12828. }
  12829. nsCOMPtr<nsIChannel> channel;
  12830. nsresult rv = aChannel->GetChannel(getter_AddRefs(channel));
  12831. NS_ENSURE_SUCCESS(rv, rv);
  12832. nsCOMPtr<nsIDocument> doc;
  12833. bool isSubresourceLoad = !nsContentUtils::IsNonSubresourceRequest(channel);
  12834. if (isSubresourceLoad) {
  12835. doc = GetDocument();
  12836. if (!doc) {
  12837. return NS_ERROR_NOT_AVAILABLE;
  12838. }
  12839. } else {
  12840. // For top-level navigations, save a document ID which will be passed to
  12841. // the FetchEvent as the clientId later on.
  12842. rv = nsIDocument::GenerateDocumentId(mInterceptedDocumentId);
  12843. NS_ENSURE_SUCCESS(rv, rv);
  12844. }
  12845. bool isReload = mLoadType & LOAD_CMD_RELOAD;
  12846. nsCOMPtr<nsIURI> uri;
  12847. rv = channel->GetURI(getter_AddRefs(uri));
  12848. NS_ENSURE_SUCCESS(rv, rv);
  12849. PrincipalOriginAttributes attrs;
  12850. attrs.InheritFromDocShellToDoc(mOriginAttributes, uri);
  12851. ErrorResult error;
  12852. swm->DispatchFetchEvent(attrs, doc, mInterceptedDocumentId, aChannel,
  12853. isReload, isSubresourceLoad, error);
  12854. if (NS_WARN_IF(error.Failed())) {
  12855. return error.StealNSResult();
  12856. }
  12857. return NS_OK;
  12858. }
  12859. bool
  12860. nsDocShell::InFrameSwap()
  12861. {
  12862. RefPtr<nsDocShell> shell = this;
  12863. do {
  12864. if (shell->mInFrameSwap) {
  12865. return true;
  12866. }
  12867. shell = shell->GetParentDocshell();
  12868. } while (shell);
  12869. return false;
  12870. }
  12871. NS_IMETHODIMP
  12872. nsDocShell::IssueWarning(uint32_t aWarning, bool aAsError)
  12873. {
  12874. if (mContentViewer) {
  12875. nsCOMPtr<nsIDocument> doc = mContentViewer->GetDocument();
  12876. if (doc) {
  12877. doc->WarnOnceAbout(nsIDocument::DeprecatedOperations(aWarning), aAsError);
  12878. }
  12879. }
  12880. return NS_OK;
  12881. }
  12882. NS_IMETHODIMP
  12883. nsDocShell::GetEditingSession(nsIEditingSession** aEditSession)
  12884. {
  12885. if (!NS_SUCCEEDED(EnsureEditorData())) {
  12886. return NS_ERROR_FAILURE;
  12887. }
  12888. mEditorData->GetEditingSession(aEditSession);
  12889. return *aEditSession ? NS_OK : NS_ERROR_FAILURE;
  12890. }
  12891. NS_IMETHODIMP
  12892. nsDocShell::GetScriptableTabChild(nsITabChild** aTabChild)
  12893. {
  12894. *aTabChild = GetTabChild().take();
  12895. return *aTabChild ? NS_OK : NS_ERROR_FAILURE;
  12896. }
  12897. already_AddRefed<nsITabChild>
  12898. nsDocShell::GetTabChild()
  12899. {
  12900. nsCOMPtr<nsIDocShellTreeOwner> owner(mTreeOwner);
  12901. nsCOMPtr<nsITabChild> tc = do_GetInterface(owner);
  12902. return tc.forget();
  12903. }
  12904. nsICommandManager*
  12905. nsDocShell::GetCommandManager()
  12906. {
  12907. NS_ENSURE_SUCCESS(EnsureCommandHandler(), nullptr);
  12908. return mCommandManager;
  12909. }
  12910. NS_IMETHODIMP
  12911. nsDocShell::GetProcessLockReason(uint32_t* aReason)
  12912. {
  12913. MOZ_ASSERT(aReason);
  12914. nsPIDOMWindowOuter* outer = GetWindow();
  12915. MOZ_ASSERT(outer);
  12916. // Check if we are a toplevel window
  12917. if (outer->GetScriptableParentOrNull()) {
  12918. *aReason = PROCESS_LOCK_IFRAME;
  12919. return NS_OK;
  12920. }
  12921. // If we have any other toplevel windows in our tab group, then we cannot
  12922. // perform the navigation.
  12923. nsTArray<nsPIDOMWindowOuter*> toplevelWindows =
  12924. outer->TabGroup()->GetTopLevelWindows();
  12925. if (toplevelWindows.Length() > 1) {
  12926. *aReason = PROCESS_LOCK_RELATED_CONTEXTS;
  12927. return NS_OK;
  12928. }
  12929. MOZ_ASSERT(toplevelWindows.Length() == 1);
  12930. MOZ_ASSERT(toplevelWindows[0] == outer);
  12931. // If we aren't in a content process, we cannot perform a cross-process load.
  12932. if (!XRE_IsContentProcess()) {
  12933. *aReason = PROCESS_LOCK_NON_CONTENT;
  12934. return NS_OK;
  12935. }
  12936. *aReason = PROCESS_LOCK_NONE;
  12937. return NS_OK;
  12938. }