nsAppRunner.cpp 120 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245
  1. /* -*- Mode: C++; tab-width: 2; 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 "mozilla/dom/ContentParent.h"
  6. #include "mozilla/dom/ContentChild.h"
  7. #include "mozilla/ipc/GeckoChildProcessHost.h"
  8. #include "mozilla/ArrayUtils.h"
  9. #include "mozilla/Attributes.h"
  10. #include "mozilla/FilePreferences.h"
  11. #include "mozilla/ChaosMode.h"
  12. #include "mozilla/IOInterposer.h"
  13. #include "mozilla/Likely.h"
  14. #include "mozilla/MemoryChecking.h"
  15. #include "mozilla/Poison.h"
  16. #include "mozilla/Preferences.h"
  17. #include "mozilla/ScopeExit.h"
  18. #include "mozilla/Services.h"
  19. #include "mozilla/ServoBindings.h"
  20. #include "mozilla/Telemetry.h"
  21. #include "nsAppRunner.h"
  22. #include "mozilla/AppData.h"
  23. #ifdef MOZ_UPDATER
  24. #include "nsUpdateDriver.h"
  25. #endif
  26. #include "ProfileReset.h"
  27. #ifdef MOZ_INSTRUMENT_EVENT_LOOP
  28. #include "EventTracer.h"
  29. #endif
  30. #include "prmem.h"
  31. #include "prnetdb.h"
  32. #include "prprf.h"
  33. #include "prproces.h"
  34. #include "prenv.h"
  35. #include "prtime.h"
  36. #include "nsIAppShellService.h"
  37. #include "nsIAppStartup.h"
  38. #include "nsIAppStartupNotifier.h"
  39. #include "nsIMutableArray.h"
  40. #include "nsICategoryManager.h"
  41. #include "nsIChromeRegistry.h"
  42. #include "nsICommandLineRunner.h"
  43. #include "nsIComponentManager.h"
  44. #include "nsIComponentRegistrar.h"
  45. #include "nsIConsoleService.h"
  46. #include "nsIContentHandler.h"
  47. #include "nsIDialogParamBlock.h"
  48. #include "nsIDOMWindow.h"
  49. #include "mozilla/ModuleUtils.h"
  50. #include "nsIIOService2.h"
  51. #include "nsIObserverService.h"
  52. #include "nsINativeAppSupport.h"
  53. #include "nsIPlatformInfo.h"
  54. #include "nsIProcess.h"
  55. #include "nsIProfileUnlocker.h"
  56. #include "nsIPromptService.h"
  57. #include "nsIServiceManager.h"
  58. #include "nsIStringBundle.h"
  59. #include "nsISupportsPrimitives.h"
  60. #include "nsIToolkitChromeRegistry.h"
  61. #include "nsIToolkitProfile.h"
  62. #include "nsIToolkitProfileService.h"
  63. #include "nsIURI.h"
  64. #include "nsIURL.h"
  65. #include "nsIWindowCreator.h"
  66. #include "nsIWindowMediator.h"
  67. #include "nsIWindowWatcher.h"
  68. #include "nsIXULAppInfo.h"
  69. #include "nsIXULRuntime.h"
  70. #include "nsPIDOMWindow.h"
  71. #include "nsIBaseWindow.h"
  72. #include "nsIWidget.h"
  73. #include "nsIDocShell.h"
  74. #include "nsAppShellCID.h"
  75. #include "mozilla/scache/StartupCache.h"
  76. #include "gfxPrefs.h"
  77. #include "mozilla/Unused.h"
  78. #ifdef XP_WIN
  79. #include "nsIWinAppHelper.h"
  80. #include <windows.h>
  81. #include <intrin.h>
  82. #include <math.h>
  83. #include "cairo/cairo-features.h"
  84. #include "mozilla/mscom/MainThreadRuntime.h"
  85. #include "mozilla/widget/AudioSession.h"
  86. #ifndef PROCESS_DEP_ENABLE
  87. #define PROCESS_DEP_ENABLE 0x1
  88. #endif
  89. #endif
  90. #ifdef ACCESSIBILITY
  91. #include "nsAccessibilityService.h"
  92. #if defined(XP_WIN)
  93. #include "mozilla/a11y/Compatibility.h"
  94. #endif
  95. #endif
  96. #include "nsCRT.h"
  97. #include "nsCOMPtr.h"
  98. #include "nsDirectoryServiceDefs.h"
  99. #include "nsDirectoryServiceUtils.h"
  100. #include "nsEmbedCID.h"
  101. #include "nsNetUtil.h"
  102. #include "nsReadableUtils.h"
  103. #include "nsXPCOM.h"
  104. #include "nsXPCOMCIDInternal.h"
  105. #include "nsXPIDLString.h"
  106. #include "nsPrintfCString.h"
  107. #include "nsVersionComparator.h"
  108. #include "nsAppDirectoryServiceDefs.h"
  109. #include "nsXULAppAPI.h"
  110. #include "nsXREDirProvider.h"
  111. #include "nsToolkitCompsCID.h"
  112. #include "nsINIParser.h"
  113. #include "mozilla/Omnijar.h"
  114. #include "mozilla/StartupTimeline.h"
  115. #include "mozilla/LateWriteChecks.h"
  116. #include <stdlib.h>
  117. #include <locale.h>
  118. #ifdef XP_UNIX
  119. #include <sys/stat.h>
  120. #include <unistd.h>
  121. #include <pwd.h>
  122. #endif
  123. #ifdef XP_WIN
  124. #include <process.h>
  125. #include <shlobj.h>
  126. #include "nsThreadUtils.h"
  127. #include <comdef.h>
  128. #include <wbemidl.h>
  129. #include "WinUtils.h"
  130. #endif
  131. // for X remote support
  132. #ifdef MOZ_ENABLE_XREMOTE
  133. #include "XRemoteClient.h"
  134. #include "nsIRemoteService.h"
  135. #include "nsProfileLock.h"
  136. #include "SpecialSystemDirectory.h"
  137. #include <sched.h>
  138. // Time to wait for the remoting service to start
  139. #define MOZ_XREMOTE_START_TIMEOUT_SEC 5
  140. #endif
  141. #if defined(DEBUG) && defined(XP_WIN32)
  142. #include <malloc.h>
  143. #endif
  144. #ifdef DEBUG
  145. #include "mozilla/Logging.h"
  146. #endif
  147. #include "base/command_line.h"
  148. #include "GTestRunner.h"
  149. extern uint32_t gRestartMode;
  150. extern void InstallSignalHandlers(const char *ProgramName);
  151. #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
  152. #define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")
  153. int gArgc;
  154. char **gArgv;
  155. static const char gToolkitVersion[] = NS_STRINGIFY(GRE_MILESTONE);
  156. static const char gToolkitBuildID[] = NS_STRINGIFY(MOZ_BUILDID);
  157. static nsIProfileLock* gProfileLock;
  158. int gRestartArgc;
  159. char **gRestartArgv;
  160. bool gIsGtest = false;
  161. nsString gAbsoluteArgv0Path;
  162. #if defined(MOZ_WIDGET_GTK)
  163. #include <glib.h>
  164. #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING)
  165. #define CLEANUP_MEMORY 1
  166. #define PANGO_ENABLE_BACKEND
  167. #include <pango/pangofc-fontmap.h>
  168. #endif
  169. #include <gtk/gtk.h>
  170. #ifdef MOZ_X11
  171. #include <gdk/gdkx.h>
  172. #endif /* MOZ_X11 */
  173. #include "nsGTKToolkit.h"
  174. #include <fontconfig/fontconfig.h>
  175. #endif
  176. #include "BinaryPath.h"
  177. #ifndef MOZ_BUILDID
  178. // See comment in Makefile.in why we want to avoid including buildid.h.
  179. // Still include it when MOZ_BUILDID is not set, which can happen with some
  180. // build backends.
  181. #include "buildid.h"
  182. #endif
  183. #ifdef MOZ_LINKER
  184. extern "C" MFBT_API bool IsSignalHandlingBroken();
  185. #endif
  186. #ifdef LIBFUZZER
  187. #include "LibFuzzerRunner.h"
  188. namespace mozilla {
  189. LibFuzzerRunner* libFuzzerRunner = 0;
  190. } // namespace mozilla
  191. extern "C" MOZ_EXPORT void XRE_LibFuzzerSetMain(int argc, char** argv, LibFuzzerMain main) {
  192. mozilla::libFuzzerRunner->setParams(argc, argv, main);
  193. }
  194. #endif
  195. namespace mozilla {
  196. int (*RunGTest)() = 0;
  197. } // namespace mozilla
  198. using namespace mozilla;
  199. using mozilla::Unused;
  200. using mozilla::scache::StartupCache;
  201. using mozilla::dom::ContentParent;
  202. using mozilla::dom::ContentChild;
  203. // Save literal putenv string to environment variable.
  204. static void
  205. SaveToEnv(const char *putenv)
  206. {
  207. char *expr = strdup(putenv);
  208. if (expr)
  209. PR_SetEnv(expr);
  210. // We intentionally leak |expr| here since it is required by PR_SetEnv.
  211. MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(expr);
  212. }
  213. // Tests that an environment variable exists and has a value
  214. static bool
  215. EnvHasValue(const char *name)
  216. {
  217. const char *val = PR_GetEnv(name);
  218. return (val && *val);
  219. }
  220. // Save the given word to the specified environment variable.
  221. static void
  222. SaveWordToEnv(const char *name, const nsACString & word)
  223. {
  224. char *expr = PR_smprintf("%s=%s", name, PromiseFlatCString(word).get());
  225. if (expr)
  226. PR_SetEnv(expr);
  227. // We intentionally leak |expr| here since it is required by PR_SetEnv.
  228. }
  229. // Save the path of the given file to the specified environment variable.
  230. static void
  231. SaveFileToEnv(const char *name, nsIFile *file)
  232. {
  233. #ifdef XP_WIN
  234. nsAutoString path;
  235. file->GetPath(path);
  236. SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
  237. #else
  238. nsAutoCString path;
  239. file->GetNativePath(path);
  240. SaveWordToEnv(name, path);
  241. #endif
  242. }
  243. // Load the path of a file saved with SaveFileToEnv
  244. static already_AddRefed<nsIFile>
  245. GetFileFromEnv(const char *name)
  246. {
  247. nsresult rv;
  248. nsCOMPtr<nsIFile> file;
  249. #ifdef XP_WIN
  250. WCHAR path[_MAX_PATH];
  251. if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(),
  252. path, _MAX_PATH))
  253. return nullptr;
  254. rv = NS_NewLocalFile(nsDependentString(path), true, getter_AddRefs(file));
  255. if (NS_FAILED(rv))
  256. return nullptr;
  257. return file.forget();
  258. #else
  259. const char *arg = PR_GetEnv(name);
  260. if (!arg || !*arg)
  261. return nullptr;
  262. rv = NS_NewNativeLocalFile(nsDependentCString(arg), true,
  263. getter_AddRefs(file));
  264. if (NS_FAILED(rv))
  265. return nullptr;
  266. return file.forget();
  267. #endif
  268. }
  269. // Save the path of the given word to the specified environment variable
  270. // provided the environment variable does not have a value.
  271. static void
  272. SaveWordToEnvIfUnset(const char *name, const nsACString & word)
  273. {
  274. if (!EnvHasValue(name))
  275. SaveWordToEnv(name, word);
  276. }
  277. // Save the path of the given file to the specified environment variable
  278. // provided the environment variable does not have a value.
  279. static void
  280. SaveFileToEnvIfUnset(const char *name, nsIFile *file)
  281. {
  282. if (!EnvHasValue(name))
  283. SaveFileToEnv(name, file);
  284. }
  285. static bool
  286. strimatch(const char* lowerstr, const char* mixedstr)
  287. {
  288. while(*lowerstr) {
  289. if (!*mixedstr) return false; // mixedstr is shorter
  290. if (tolower(*mixedstr) != *lowerstr) return false; // no match
  291. ++lowerstr;
  292. ++mixedstr;
  293. }
  294. if (*mixedstr) return false; // lowerstr is shorter
  295. return true;
  296. }
  297. static bool gIsExpectedExit = false;
  298. void MozExpectedExit() {
  299. gIsExpectedExit = true;
  300. }
  301. /**
  302. * Runs atexit() to catch unexpected exit from 3rd party libraries like the
  303. * Intel graphics driver calling exit in an error condition. When they
  304. * call exit() to report an error we won't shutdown correctly and wont catch
  305. * the issue with our crash reporter.
  306. */
  307. static void UnexpectedExit() {
  308. if (!gIsExpectedExit) {
  309. gIsExpectedExit = true; // Don't risk re-entrency issues when crashing.
  310. MOZ_CRASH("Exit called by third party code.");
  311. }
  312. }
  313. /**
  314. * Output a string to the user. This method is really only meant to be used to
  315. * output last-ditch error messages designed for developers NOT END USERS.
  316. *
  317. * @param isError
  318. * Pass true to indicate severe errors.
  319. * @param fmt
  320. * printf-style format string followed by arguments.
  321. */
  322. static void Output(bool isError, const char *fmt, ... )
  323. {
  324. va_list ap;
  325. va_start(ap, fmt);
  326. #if defined(XP_WIN) && !MOZ_WINCONSOLE
  327. char *msg = PR_vsmprintf(fmt, ap);
  328. if (msg)
  329. {
  330. UINT flags = MB_OK;
  331. if (isError)
  332. flags |= MB_ICONERROR;
  333. else
  334. flags |= MB_ICONINFORMATION;
  335. wchar_t wide_msg[1024];
  336. MultiByteToWideChar(CP_ACP,
  337. 0,
  338. msg,
  339. -1,
  340. wide_msg,
  341. sizeof(wide_msg) / sizeof(wchar_t));
  342. MessageBoxW(nullptr, wide_msg, L"XULRunner", flags);
  343. PR_smprintf_free(msg);
  344. }
  345. #else
  346. vfprintf(stderr, fmt, ap);
  347. #endif
  348. va_end(ap);
  349. }
  350. enum RemoteResult {
  351. REMOTE_NOT_FOUND = 0,
  352. REMOTE_FOUND = 1,
  353. REMOTE_ARG_BAD = 2
  354. };
  355. enum ArgResult {
  356. ARG_NONE = 0,
  357. ARG_FOUND = 1,
  358. ARG_BAD = 2 // you wanted a param, but there isn't one
  359. };
  360. static void RemoveArg(char **argv)
  361. {
  362. do {
  363. *argv = *(argv + 1);
  364. ++argv;
  365. } while (*argv);
  366. --gArgc;
  367. }
  368. /**
  369. * Check for a commandline flag. If the flag takes a parameter, the
  370. * parameter is returned in aParam. Flags may be in the form -arg or
  371. * --arg (or /arg on win32).
  372. *
  373. * @param aArg the parameter to check. Must be lowercase.
  374. * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
  375. * when aArg is also present.
  376. * @param aParam if non-null, the -arg <data> will be stored in this pointer.
  377. * This is *not* allocated, but rather a pointer to the argv data.
  378. * @param aRemArg if true, the argument is removed from the gArgv array.
  379. */
  380. static ArgResult
  381. CheckArg(const char* aArg, bool aCheckOSInt = false, const char **aParam = nullptr, bool aRemArg = true)
  382. {
  383. MOZ_ASSERT(gArgv, "gArgv must be initialized before CheckArg()");
  384. char **curarg = gArgv + 1; // skip argv[0]
  385. ArgResult ar = ARG_NONE;
  386. while (*curarg) {
  387. char *arg = curarg[0];
  388. if (arg[0] == '-'
  389. #if defined(XP_WIN)
  390. || *arg == '/'
  391. #endif
  392. ) {
  393. ++arg;
  394. if (*arg == '-')
  395. ++arg;
  396. if (strimatch(aArg, arg)) {
  397. if (aRemArg)
  398. RemoveArg(curarg);
  399. else
  400. ++curarg;
  401. if (!aParam) {
  402. ar = ARG_FOUND;
  403. break;
  404. }
  405. if (*curarg) {
  406. if (**curarg == '-'
  407. #if defined(XP_WIN)
  408. || **curarg == '/'
  409. #endif
  410. )
  411. return ARG_BAD;
  412. *aParam = *curarg;
  413. if (aRemArg)
  414. RemoveArg(curarg);
  415. ar = ARG_FOUND;
  416. break;
  417. }
  418. return ARG_BAD;
  419. }
  420. }
  421. ++curarg;
  422. }
  423. if (aCheckOSInt && ar == ARG_FOUND) {
  424. ArgResult arOSInt = CheckArg("osint");
  425. if (arOSInt == ARG_FOUND) {
  426. ar = ARG_BAD;
  427. PR_fprintf(PR_STDERR, "Error: argument --osint is invalid\n");
  428. }
  429. }
  430. return ar;
  431. }
  432. #if defined(XP_WIN)
  433. /**
  434. * Check for a commandline flag from the windows shell and remove it from the
  435. * argv used when restarting. Flags MUST be in the form -arg.
  436. *
  437. * @param aArg the parameter to check. Must be lowercase.
  438. */
  439. static ArgResult
  440. CheckArgShell(const char* aArg)
  441. {
  442. char **curarg = gRestartArgv + 1; // skip argv[0]
  443. while (*curarg) {
  444. char *arg = curarg[0];
  445. if (arg[0] == '-') {
  446. ++arg;
  447. if (strimatch(aArg, arg)) {
  448. do {
  449. *curarg = *(curarg + 1);
  450. ++curarg;
  451. } while (*curarg);
  452. --gRestartArgc;
  453. return ARG_FOUND;
  454. }
  455. }
  456. ++curarg;
  457. }
  458. return ARG_NONE;
  459. }
  460. /**
  461. * Enabled Native App Support to process DDE messages when the app needs to
  462. * restart and the app has been launched by the Windows shell to open an url.
  463. * When aWait is false this will process the DDE events manually. This prevents
  464. * Windows from displaying an error message due to the DDE message not being
  465. * acknowledged.
  466. */
  467. static void
  468. ProcessDDE(nsINativeAppSupport* aNative, bool aWait)
  469. {
  470. // When the app is launched by the windows shell the windows shell
  471. // expects the app to be available for DDE messages and if it isn't
  472. // windows displays an error dialog. To prevent the error the DDE server
  473. // is enabled and pending events are processed when the app needs to
  474. // restart after it was launched by the shell with the requestpending
  475. // argument. The requestpending pending argument is removed to
  476. // differentiate it from being launched when an app restart is not
  477. // required.
  478. ArgResult ar;
  479. ar = CheckArgShell("requestpending");
  480. if (ar == ARG_FOUND) {
  481. aNative->Enable(); // enable win32 DDE responses
  482. if (aWait) {
  483. nsIThread *thread = NS_GetCurrentThread();
  484. // This is just a guesstimate based on testing different values.
  485. // If count is 8 or less windows will display an error dialog.
  486. int32_t count = 20;
  487. while(--count >= 0) {
  488. NS_ProcessNextEvent(thread);
  489. PR_Sleep(PR_MillisecondsToInterval(1));
  490. }
  491. }
  492. }
  493. }
  494. #endif
  495. /**
  496. * Determines if there is support for showing the profile manager
  497. *
  498. * @return true in all environments
  499. */
  500. static bool
  501. CanShowProfileManager()
  502. {
  503. return true;
  504. }
  505. bool gSafeMode = false;
  506. /**
  507. * The nsXULAppInfo object implements nsIFactory so that it can be its own
  508. * singleton.
  509. */
  510. class nsXULAppInfo : public nsIXULAppInfo,
  511. public nsIObserver,
  512. #ifdef XP_WIN
  513. public nsIWinAppHelper,
  514. #endif
  515. public nsIXULRuntime
  516. {
  517. public:
  518. constexpr nsXULAppInfo() {}
  519. NS_DECL_ISUPPORTS_INHERITED
  520. NS_DECL_NSIPLATFORMINFO
  521. NS_DECL_NSIXULAPPINFO
  522. NS_DECL_NSIXULRUNTIME
  523. NS_DECL_NSIOBSERVER
  524. #ifdef XP_WIN
  525. NS_DECL_NSIWINAPPHELPER
  526. #endif
  527. };
  528. NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
  529. NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
  530. NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
  531. NS_INTERFACE_MAP_ENTRY(nsIObserver)
  532. #ifdef XP_WIN
  533. NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
  534. #endif
  535. NS_INTERFACE_MAP_ENTRY(nsIPlatformInfo)
  536. NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData ||
  537. XRE_IsContentProcess())
  538. NS_INTERFACE_MAP_END
  539. NS_IMETHODIMP_(MozExternalRefCountType)
  540. nsXULAppInfo::AddRef()
  541. {
  542. return 1;
  543. }
  544. NS_IMETHODIMP_(MozExternalRefCountType)
  545. nsXULAppInfo::Release()
  546. {
  547. return 1;
  548. }
  549. NS_IMETHODIMP
  550. nsXULAppInfo::GetVendor(nsACString& aResult)
  551. {
  552. if (XRE_IsContentProcess()) {
  553. ContentChild* cc = ContentChild::GetSingleton();
  554. aResult = cc->GetAppInfo().vendor;
  555. return NS_OK;
  556. }
  557. aResult.Assign(gAppData->vendor);
  558. return NS_OK;
  559. }
  560. NS_IMETHODIMP
  561. nsXULAppInfo::GetName(nsACString& aResult)
  562. {
  563. if (XRE_IsContentProcess()) {
  564. ContentChild* cc = ContentChild::GetSingleton();
  565. aResult = cc->GetAppInfo().name;
  566. return NS_OK;
  567. }
  568. aResult.Assign(gAppData->name);
  569. return NS_OK;
  570. }
  571. NS_IMETHODIMP
  572. nsXULAppInfo::GetID(nsACString& aResult)
  573. {
  574. if (XRE_IsContentProcess()) {
  575. ContentChild* cc = ContentChild::GetSingleton();
  576. aResult = cc->GetAppInfo().ID;
  577. return NS_OK;
  578. }
  579. aResult.Assign(gAppData->ID);
  580. return NS_OK;
  581. }
  582. NS_IMETHODIMP
  583. nsXULAppInfo::GetVersion(nsACString& aResult)
  584. {
  585. if (XRE_IsContentProcess()) {
  586. ContentChild* cc = ContentChild::GetSingleton();
  587. aResult = cc->GetAppInfo().version;
  588. return NS_OK;
  589. }
  590. aResult.Assign(gAppData->version);
  591. return NS_OK;
  592. }
  593. NS_IMETHODIMP
  594. nsXULAppInfo::GetPlatformVersion(nsACString& aResult)
  595. {
  596. aResult.Assign(gToolkitVersion);
  597. return NS_OK;
  598. }
  599. NS_IMETHODIMP
  600. nsXULAppInfo::GetAppBuildID(nsACString& aResult)
  601. {
  602. if (XRE_IsContentProcess()) {
  603. ContentChild* cc = ContentChild::GetSingleton();
  604. aResult = cc->GetAppInfo().buildID;
  605. return NS_OK;
  606. }
  607. aResult.Assign(gAppData->buildID);
  608. return NS_OK;
  609. }
  610. NS_IMETHODIMP
  611. nsXULAppInfo::GetPlatformBuildID(nsACString& aResult)
  612. {
  613. aResult.Assign(gToolkitBuildID);
  614. return NS_OK;
  615. }
  616. NS_IMETHODIMP
  617. nsXULAppInfo::GetUAName(nsACString& aResult)
  618. {
  619. if (XRE_IsContentProcess()) {
  620. ContentChild* cc = ContentChild::GetSingleton();
  621. aResult = cc->GetAppInfo().UAName;
  622. return NS_OK;
  623. }
  624. aResult.Assign(gAppData->UAName);
  625. return NS_OK;
  626. }
  627. NS_IMETHODIMP
  628. nsXULAppInfo::GetLogConsoleErrors(bool *aResult)
  629. {
  630. *aResult = gLogConsoleErrors;
  631. return NS_OK;
  632. }
  633. NS_IMETHODIMP
  634. nsXULAppInfo::SetLogConsoleErrors(bool aValue)
  635. {
  636. gLogConsoleErrors = aValue;
  637. return NS_OK;
  638. }
  639. NS_IMETHODIMP
  640. nsXULAppInfo::GetInSafeMode(bool *aResult)
  641. {
  642. *aResult = gSafeMode;
  643. return NS_OK;
  644. }
  645. NS_IMETHODIMP
  646. nsXULAppInfo::GetOS(nsACString& aResult)
  647. {
  648. aResult.AssignLiteral(OS_TARGET);
  649. return NS_OK;
  650. }
  651. NS_IMETHODIMP
  652. nsXULAppInfo::GetXPCOMABI(nsACString& aResult)
  653. {
  654. #ifdef TARGET_XPCOM_ABI
  655. aResult.AssignLiteral(TARGET_XPCOM_ABI);
  656. return NS_OK;
  657. #else
  658. return NS_ERROR_NOT_AVAILABLE;
  659. #endif
  660. }
  661. NS_IMETHODIMP
  662. nsXULAppInfo::GetWidgetToolkit(nsACString& aResult)
  663. {
  664. aResult.AssignLiteral(MOZ_WIDGET_TOOLKIT);
  665. return NS_OK;
  666. }
  667. // Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,
  668. // is synchronized with the const unsigned longs defined in
  669. // xpcom/system/nsIXULRuntime.idl.
  670. #define SYNC_ENUMS(a,b) \
  671. static_assert(nsIXULRuntime::PROCESS_TYPE_ ## a == \
  672. static_cast<int>(GeckoProcessType_ ## b), \
  673. "GeckoProcessType in nsXULAppAPI.h not synchronized with nsIXULRuntime.idl");
  674. SYNC_ENUMS(DEFAULT, Default)
  675. SYNC_ENUMS(PLUGIN, Plugin)
  676. SYNC_ENUMS(CONTENT, Content)
  677. SYNC_ENUMS(IPDLUNITTEST, IPDLUnitTest)
  678. SYNC_ENUMS(GMPLUGIN, GMPlugin)
  679. SYNC_ENUMS(GPU, GPU)
  680. // .. and ensure that that is all of them:
  681. static_assert(GeckoProcessType_GPU + 1 == GeckoProcessType_End,
  682. "Did not find the final GeckoProcessType");
  683. NS_IMETHODIMP
  684. nsXULAppInfo::GetProcessType(uint32_t* aResult)
  685. {
  686. NS_ENSURE_ARG_POINTER(aResult);
  687. *aResult = XRE_GetProcessType();
  688. return NS_OK;
  689. }
  690. NS_IMETHODIMP
  691. nsXULAppInfo::GetProcessID(uint32_t* aResult)
  692. {
  693. #ifdef XP_WIN
  694. *aResult = GetCurrentProcessId();
  695. #else
  696. *aResult = getpid();
  697. #endif
  698. return NS_OK;
  699. }
  700. NS_IMETHODIMP
  701. nsXULAppInfo::GetUniqueProcessID(uint64_t* aResult)
  702. {
  703. if (XRE_IsContentProcess()) {
  704. ContentChild* cc = ContentChild::GetSingleton();
  705. *aResult = cc->GetID();
  706. } else {
  707. *aResult = 0;
  708. }
  709. return NS_OK;
  710. }
  711. static bool gBrowserTabsRemoteAutostart = false;
  712. static uint64_t gBrowserTabsRemoteStatus = 0;
  713. static bool gBrowserTabsRemoteAutostartInitialized = false;
  714. static bool gMultiprocessBlockPolicyInitialized = false;
  715. static uint32_t gMultiprocessBlockPolicy = 0;
  716. NS_IMETHODIMP
  717. nsXULAppInfo::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData) {
  718. if (!nsCRT::strcmp(aTopic, "getE10SBlocked")) {
  719. nsCOMPtr<nsISupportsPRUint64> ret = do_QueryInterface(aSubject);
  720. if (!ret)
  721. return NS_ERROR_FAILURE;
  722. ret->SetData(gBrowserTabsRemoteStatus);
  723. return NS_OK;
  724. }
  725. return NS_ERROR_FAILURE;
  726. }
  727. NS_IMETHODIMP
  728. nsXULAppInfo::GetBrowserTabsRemoteAutostart(bool* aResult)
  729. {
  730. *aResult = BrowserTabsRemoteAutostart();
  731. return NS_OK;
  732. }
  733. NS_IMETHODIMP
  734. nsXULAppInfo::GetMultiprocessBlockPolicy(uint32_t* aResult)
  735. {
  736. *aResult = MultiprocessBlockPolicy();
  737. return NS_OK;
  738. }
  739. NS_IMETHODIMP
  740. nsXULAppInfo::GetAccessibilityEnabled(bool* aResult)
  741. {
  742. #ifdef ACCESSIBILITY
  743. *aResult = GetAccService() != nullptr;
  744. #else
  745. *aResult = false;
  746. #endif
  747. return NS_OK;
  748. }
  749. NS_IMETHODIMP
  750. nsXULAppInfo::GetIs64Bit(bool* aResult)
  751. {
  752. #ifdef HAVE_64BIT_BUILD
  753. *aResult = true;
  754. #else
  755. *aResult = false;
  756. #endif
  757. return NS_OK;
  758. }
  759. NS_IMETHODIMP
  760. nsXULAppInfo::EnsureContentProcess()
  761. {
  762. if (!XRE_IsParentProcess())
  763. return NS_ERROR_NOT_AVAILABLE;
  764. RefPtr<ContentParent> unused = ContentParent::GetNewOrUsedBrowserProcess();
  765. return NS_OK;
  766. }
  767. NS_IMETHODIMP
  768. nsXULAppInfo::InvalidateCachesOnRestart()
  769. {
  770. nsCOMPtr<nsIFile> file;
  771. nsresult rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP,
  772. getter_AddRefs(file));
  773. if (NS_FAILED(rv))
  774. return rv;
  775. if (!file)
  776. return NS_ERROR_NOT_AVAILABLE;
  777. file->AppendNative(FILE_COMPATIBILITY_INFO);
  778. nsINIParser parser;
  779. rv = parser.Init(file);
  780. if (NS_FAILED(rv)) {
  781. // This fails if compatibility.ini is not there, so we'll
  782. // flush the caches on the next restart anyways.
  783. return NS_OK;
  784. }
  785. nsAutoCString buf;
  786. rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
  787. if (NS_FAILED(rv)) {
  788. PRFileDesc *fd;
  789. rv = file->OpenNSPRFileDesc(PR_RDWR | PR_APPEND, 0600, &fd);
  790. if (NS_FAILED(rv)) {
  791. NS_ERROR("could not create output stream");
  792. return NS_ERROR_NOT_AVAILABLE;
  793. }
  794. static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1" NS_LINEBREAK;
  795. PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
  796. PR_Close(fd);
  797. }
  798. return NS_OK;
  799. }
  800. NS_IMETHODIMP
  801. nsXULAppInfo::GetReplacedLockTime(PRTime *aReplacedLockTime)
  802. {
  803. if (!gProfileLock)
  804. return NS_ERROR_NOT_AVAILABLE;
  805. gProfileLock->GetReplacedLockTime(aReplacedLockTime);
  806. return NS_OK;
  807. }
  808. NS_IMETHODIMP
  809. nsXULAppInfo::GetLastRunCrashID(nsAString &aLastRunCrashID)
  810. {
  811. return NS_ERROR_NOT_IMPLEMENTED;
  812. }
  813. NS_IMETHODIMP
  814. nsXULAppInfo::GetIsReleaseOrBeta(bool* aResult)
  815. {
  816. #ifdef RELEASE_OR_BETA
  817. *aResult = true;
  818. #else
  819. *aResult = false;
  820. #endif
  821. return NS_OK;
  822. }
  823. NS_IMETHODIMP
  824. nsXULAppInfo::GetIsOfficialBranding(bool* aResult)
  825. {
  826. #ifdef MOZ_OFFICIAL_BRANDING
  827. *aResult = true;
  828. #else
  829. *aResult = false;
  830. #endif
  831. return NS_OK;
  832. }
  833. NS_IMETHODIMP
  834. nsXULAppInfo::GetDefaultUpdateChannel(nsACString& aResult)
  835. {
  836. aResult.AssignLiteral(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
  837. return NS_OK;
  838. }
  839. NS_IMETHODIMP
  840. nsXULAppInfo::GetDistributionID(nsACString& aResult)
  841. {
  842. aResult.AssignLiteral(MOZ_DISTRIBUTION_ID);
  843. return NS_OK;
  844. }
  845. NS_IMETHODIMP
  846. nsXULAppInfo::GetIsOfficial(bool* aResult)
  847. {
  848. #ifdef MC_OFFICIAL
  849. *aResult = true;
  850. #else
  851. *aResult = false;
  852. #endif
  853. return NS_OK;
  854. }
  855. NS_IMETHODIMP
  856. nsXULAppInfo::GetWindowsDLLBlocklistStatus(bool* aResult)
  857. {
  858. #if defined(XP_WIN)
  859. *aResult = gAppData->flags & NS_XRE_DLL_BLOCKLIST_ENABLED;
  860. #else
  861. *aResult = false;
  862. #endif
  863. return NS_OK;
  864. }
  865. #ifdef XP_WIN
  866. // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
  867. // safely build with the Vista SDK and without it.
  868. typedef enum
  869. {
  870. VistaTokenElevationTypeDefault = 1,
  871. VistaTokenElevationTypeFull,
  872. VistaTokenElevationTypeLimited
  873. } VISTA_TOKEN_ELEVATION_TYPE;
  874. // avoid collision with TokeElevationType enum in WinNT.h
  875. // of the Vista SDK
  876. #define VistaTokenElevationType static_cast< TOKEN_INFORMATION_CLASS >( 18 )
  877. NS_IMETHODIMP
  878. nsXULAppInfo::GetUserCanElevate(bool *aUserCanElevate)
  879. {
  880. HANDLE hToken;
  881. VISTA_TOKEN_ELEVATION_TYPE elevationType;
  882. DWORD dwSize;
  883. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) ||
  884. !GetTokenInformation(hToken, VistaTokenElevationType, &elevationType,
  885. sizeof(elevationType), &dwSize)) {
  886. *aUserCanElevate = false;
  887. }
  888. else {
  889. // The possible values returned for elevationType and their meanings are:
  890. // TokenElevationTypeDefault: The token does not have a linked token
  891. // (e.g. UAC disabled or a standard user, so they can't be elevated)
  892. // TokenElevationTypeFull: The token is linked to an elevated token
  893. // (e.g. UAC is enabled and the user is already elevated so they can't
  894. // be elevated again)
  895. // TokenElevationTypeLimited: The token is linked to a limited token
  896. // (e.g. UAC is enabled and the user is not elevated, so they can be
  897. // elevated)
  898. *aUserCanElevate = (elevationType == VistaTokenElevationTypeLimited);
  899. }
  900. if (hToken)
  901. CloseHandle(hToken);
  902. return NS_OK;
  903. }
  904. #endif
  905. static const nsXULAppInfo kAppInfo;
  906. static nsresult AppInfoConstructor(nsISupports* aOuter,
  907. REFNSIID aIID, void **aResult)
  908. {
  909. NS_ENSURE_NO_AGGREGATION(aOuter);
  910. return const_cast<nsXULAppInfo*>(&kAppInfo)->
  911. QueryInterface(aIID, aResult);
  912. }
  913. bool gLogConsoleErrors = false;
  914. #define NS_ENSURE_TRUE_LOG(x, ret) \
  915. PR_BEGIN_MACRO \
  916. if (MOZ_UNLIKELY(!(x))) { \
  917. NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
  918. gLogConsoleErrors = true; \
  919. return ret; \
  920. } \
  921. PR_END_MACRO
  922. #define NS_ENSURE_SUCCESS_LOG(res, ret) \
  923. NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)
  924. /**
  925. * Because we're starting/stopping XPCOM several times in different scenarios,
  926. * this class is a stack-based critter that makes sure that XPCOM is shut down
  927. * during early returns.
  928. */
  929. class ScopedXPCOMStartup
  930. {
  931. public:
  932. ScopedXPCOMStartup() :
  933. mServiceManager(nullptr) { }
  934. ~ScopedXPCOMStartup();
  935. nsresult Initialize();
  936. nsresult SetWindowCreator(nsINativeAppSupport* native);
  937. static nsresult CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult);
  938. private:
  939. nsIServiceManager* mServiceManager;
  940. static nsINativeAppSupport* gNativeAppSupport;
  941. };
  942. ScopedXPCOMStartup::~ScopedXPCOMStartup()
  943. {
  944. NS_IF_RELEASE(gNativeAppSupport);
  945. if (mServiceManager) {
  946. nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
  947. if (appStartup)
  948. appStartup->DestroyHiddenWindow();
  949. gDirServiceProvider->DoShutdown();
  950. PROFILER_MARKER("Shutdown early");
  951. WriteConsoleLog();
  952. NS_ShutdownXPCOM(mServiceManager);
  953. mServiceManager = nullptr;
  954. }
  955. }
  956. // {95d89e3e-a169-41a3-8e56-719978e15b12}
  957. #define APPINFO_CID \
  958. { 0x95d89e3e, 0xa169, 0x41a3, { 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 } }
  959. // {0C4A446C-EE82-41f2-8D04-D366D2C7A7D4}
  960. static const nsCID kNativeAppSupportCID =
  961. { 0xc4a446c, 0xee82, 0x41f2, { 0x8d, 0x4, 0xd3, 0x66, 0xd2, 0xc7, 0xa7, 0xd4 } };
  962. // {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}
  963. static const nsCID kProfileServiceCID =
  964. { 0x5f5e59ce, 0x27bc, 0x47eb, { 0x9d, 0x1f, 0xb0, 0x9c, 0xa9, 0x4, 0x98, 0x36 } };
  965. static already_AddRefed<nsIFactory>
  966. ProfileServiceFactoryConstructor(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry)
  967. {
  968. nsCOMPtr<nsIFactory> factory;
  969. NS_NewToolkitProfileFactory(getter_AddRefs(factory));
  970. return factory.forget();
  971. }
  972. NS_DEFINE_NAMED_CID(APPINFO_CID);
  973. static const mozilla::Module::CIDEntry kXRECIDs[] = {
  974. { &kAPPINFO_CID, false, nullptr, AppInfoConstructor },
  975. { &kProfileServiceCID, false, ProfileServiceFactoryConstructor, nullptr },
  976. { &kNativeAppSupportCID, false, nullptr, ScopedXPCOMStartup::CreateAppSupport },
  977. { nullptr }
  978. };
  979. static const mozilla::Module::ContractIDEntry kXREContracts[] = {
  980. { XULAPPINFO_SERVICE_CONTRACTID, &kAPPINFO_CID },
  981. { XULRUNTIME_SERVICE_CONTRACTID, &kAPPINFO_CID },
  982. { NS_PROFILESERVICE_CONTRACTID, &kProfileServiceCID },
  983. { NS_NATIVEAPPSUPPORT_CONTRACTID, &kNativeAppSupportCID },
  984. { nullptr }
  985. };
  986. static const mozilla::Module kXREModule = {
  987. mozilla::Module::kVersion,
  988. kXRECIDs,
  989. kXREContracts
  990. };
  991. NSMODULE_DEFN(Apprunner) = &kXREModule;
  992. nsresult
  993. ScopedXPCOMStartup::Initialize()
  994. {
  995. NS_ASSERTION(gDirServiceProvider, "Should not get here!");
  996. nsresult rv;
  997. rv = NS_InitXPCOM2(&mServiceManager, gDirServiceProvider->GetAppDir(),
  998. gDirServiceProvider);
  999. if (NS_FAILED(rv)) {
  1000. NS_ERROR("Couldn't start xpcom!");
  1001. mServiceManager = nullptr;
  1002. }
  1003. else {
  1004. #ifdef DEBUG
  1005. nsCOMPtr<nsIComponentRegistrar> reg =
  1006. do_QueryInterface(mServiceManager);
  1007. NS_ASSERTION(reg, "Service Manager doesn't QI to Registrar.");
  1008. #endif
  1009. }
  1010. return rv;
  1011. }
  1012. /**
  1013. * This is a little factory class that serves as a singleton-service-factory
  1014. * for the nativeappsupport object.
  1015. */
  1016. class nsSingletonFactory final : public nsIFactory
  1017. {
  1018. public:
  1019. NS_DECL_ISUPPORTS
  1020. NS_DECL_NSIFACTORY
  1021. explicit nsSingletonFactory(nsISupports* aSingleton);
  1022. private:
  1023. ~nsSingletonFactory() { }
  1024. nsCOMPtr<nsISupports> mSingleton;
  1025. };
  1026. nsSingletonFactory::nsSingletonFactory(nsISupports* aSingleton)
  1027. : mSingleton(aSingleton)
  1028. {
  1029. NS_ASSERTION(mSingleton, "Singleton was null!");
  1030. }
  1031. NS_IMPL_ISUPPORTS(nsSingletonFactory, nsIFactory)
  1032. NS_IMETHODIMP
  1033. nsSingletonFactory::CreateInstance(nsISupports* aOuter,
  1034. const nsIID& aIID,
  1035. void* *aResult)
  1036. {
  1037. NS_ENSURE_NO_AGGREGATION(aOuter);
  1038. return mSingleton->QueryInterface(aIID, aResult);
  1039. }
  1040. NS_IMETHODIMP
  1041. nsSingletonFactory::LockFactory(bool)
  1042. {
  1043. return NS_OK;
  1044. }
  1045. /**
  1046. * Set our windowcreator on the WindowWatcher service.
  1047. */
  1048. nsresult
  1049. ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport* native)
  1050. {
  1051. nsresult rv;
  1052. NS_IF_ADDREF(gNativeAppSupport = native);
  1053. // Inform the chrome registry about OS accessibility
  1054. nsCOMPtr<nsIToolkitChromeRegistry> cr =
  1055. mozilla::services::GetToolkitChromeRegistryService();
  1056. if (cr)
  1057. cr->CheckForOSAccessibility();
  1058. nsCOMPtr<nsIWindowCreator> creator (do_GetService(NS_APPSTARTUP_CONTRACTID));
  1059. if (!creator) return NS_ERROR_UNEXPECTED;
  1060. nsCOMPtr<nsIWindowWatcher> wwatch
  1061. (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
  1062. NS_ENSURE_SUCCESS(rv, rv);
  1063. return wwatch->SetWindowCreator(creator);
  1064. }
  1065. /* static */ nsresult
  1066. ScopedXPCOMStartup::CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult)
  1067. {
  1068. if (aOuter)
  1069. return NS_ERROR_NO_AGGREGATION;
  1070. if (!gNativeAppSupport)
  1071. return NS_ERROR_NOT_INITIALIZED;
  1072. return gNativeAppSupport->QueryInterface(aIID, aResult);
  1073. }
  1074. nsINativeAppSupport* ScopedXPCOMStartup::gNativeAppSupport;
  1075. static void DumpArbitraryHelp()
  1076. {
  1077. nsresult rv;
  1078. ScopedLogging log;
  1079. {
  1080. ScopedXPCOMStartup xpcom;
  1081. xpcom.Initialize();
  1082. nsCOMPtr<nsICommandLineRunner> cmdline
  1083. (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
  1084. if (!cmdline)
  1085. return;
  1086. nsCString text;
  1087. rv = cmdline->GetHelpText(text);
  1088. if (NS_SUCCEEDED(rv))
  1089. printf("%s", text.get());
  1090. }
  1091. }
  1092. // English text needs to go into a dtd file.
  1093. // But when this is called we have no components etc. These strings must either be
  1094. // here, or in a native resource file.
  1095. static void
  1096. DumpHelp()
  1097. {
  1098. printf("Usage: %s [ options ... ] [URL]\n"
  1099. " where options include:\n\n", gArgv[0]);
  1100. #ifdef MOZ_X11
  1101. printf("X11 options\n"
  1102. " --display=DISPLAY X display to use.\n"
  1103. " --sync Make X calls synchronous.\n");
  1104. #endif
  1105. #ifdef XP_UNIX
  1106. printf(" --g-fatal-warnings Make all warnings fatal.\n"
  1107. "\n%s options\n", gAppData->name);
  1108. #endif
  1109. printf(" -h or --help Print this message.\n"
  1110. " -v or --version Print %s version.\n"
  1111. " -P <profile> Start with <profile>.\n"
  1112. " --profile <path> Start with profile at <path>.\n"
  1113. #ifdef MC_BASILISK
  1114. " --migration Start with migration wizard.\n"
  1115. #endif
  1116. " --ProfileManager Start with ProfileManager.\n"
  1117. " --no-remote Do not accept or send remote commands;\n"
  1118. " implies --new-instance.\n"
  1119. " --new-instance Open new instance, not a new window\n"
  1120. " in running instance.\n"
  1121. " --UILocale <locale> Start with <locale> resources as UI Locale.\n"
  1122. " --safe-mode Disables extensions and themes for this session.\n", (const char*) gAppData->name);
  1123. #if defined(XP_WIN)
  1124. printf(" --console Start %s with a debugging console.\n", (const char*) gAppData->name);
  1125. #endif
  1126. // this works, but only after the components have registered. so if you drop in a new command line handler, --help
  1127. // won't not until the second run.
  1128. // out of the bug, because we ship a component.reg file, it works correctly.
  1129. DumpArbitraryHelp();
  1130. }
  1131. #if defined(DEBUG) && defined(XP_WIN)
  1132. #ifdef DEBUG_warren
  1133. #define _CRTDBG_MAP_ALLOC
  1134. #endif
  1135. // Set a CRT ReportHook function to capture and format MSCRT
  1136. // warnings, errors and assertions.
  1137. // See http://msdn.microsoft.com/en-US/library/74kabxyx(v=VS.80).aspx
  1138. #include <stdio.h>
  1139. #include <crtdbg.h>
  1140. #include "mozilla/mozalloc_abort.h"
  1141. static int MSCRTReportHook( int aReportType, char *aMessage, int *oReturnValue)
  1142. {
  1143. *oReturnValue = 0; // continue execution
  1144. // Do not use fprintf or other functions which may allocate
  1145. // memory from the heap which may be corrupted. Instead,
  1146. // use fputs to output the leading portion of the message
  1147. // and use mozalloc_abort to emit the remainder of the
  1148. // message.
  1149. switch(aReportType) {
  1150. case 0:
  1151. fputs("\nWARNING: CRT WARNING", stderr);
  1152. fputs(aMessage, stderr);
  1153. fputs("\n", stderr);
  1154. break;
  1155. case 1:
  1156. fputs("\n###!!! ABORT: CRT ERROR ", stderr);
  1157. mozalloc_abort(aMessage);
  1158. break;
  1159. case 2:
  1160. fputs("\n###!!! ABORT: CRT ASSERT ", stderr);
  1161. mozalloc_abort(aMessage);
  1162. break;
  1163. }
  1164. // do not invoke the debugger
  1165. return 1;
  1166. }
  1167. #endif
  1168. static inline void
  1169. DumpVersion()
  1170. {
  1171. if (gAppData->vendor)
  1172. printf("%s ", gAppData->vendor);
  1173. printf("%s %s", gAppData->name, gAppData->version);
  1174. if (gAppData->copyright)
  1175. printf(", %s", gAppData->copyright);
  1176. printf("\n");
  1177. }
  1178. #ifdef MOZ_ENABLE_XREMOTE
  1179. static RemoteResult
  1180. ParseRemoteCommandLine(nsCString& program,
  1181. const char** profile,
  1182. const char** username)
  1183. {
  1184. ArgResult ar;
  1185. ar = CheckArg("p", false, profile, false);
  1186. if (ar == ARG_BAD) {
  1187. // Leave it to the normal command line handling to handle this situation.
  1188. return REMOTE_NOT_FOUND;
  1189. }
  1190. const char *temp = nullptr;
  1191. ar = CheckArg("a", true, &temp);
  1192. if (ar == ARG_BAD) {
  1193. PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
  1194. return REMOTE_ARG_BAD;
  1195. } else if (ar == ARG_FOUND) {
  1196. program.Assign(temp);
  1197. }
  1198. ar = CheckArg("u", true, username);
  1199. if (ar == ARG_BAD) {
  1200. PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
  1201. return REMOTE_ARG_BAD;
  1202. }
  1203. return REMOTE_FOUND;
  1204. }
  1205. static RemoteResult
  1206. StartRemoteClient(const char* aDesktopStartupID,
  1207. nsCString& program,
  1208. const char* profile,
  1209. const char* username)
  1210. {
  1211. XRemoteClient client;
  1212. nsresult rv = client.Init();
  1213. if (NS_FAILED(rv))
  1214. return REMOTE_NOT_FOUND;
  1215. nsXPIDLCString response;
  1216. bool success = false;
  1217. rv = client.SendCommandLine(program.get(), username, profile,
  1218. gArgc, gArgv, aDesktopStartupID,
  1219. getter_Copies(response), &success);
  1220. // did the command fail?
  1221. if (!success)
  1222. return REMOTE_NOT_FOUND;
  1223. // The "command not parseable" error is returned when the
  1224. // nsICommandLineHandler throws a NS_ERROR_ABORT.
  1225. if (response.EqualsLiteral("500 command not parseable"))
  1226. return REMOTE_ARG_BAD;
  1227. if (NS_FAILED(rv))
  1228. return REMOTE_NOT_FOUND;
  1229. return REMOTE_FOUND;
  1230. }
  1231. #endif // MOZ_ENABLE_XREMOTE
  1232. void
  1233. XRE_InitOmnijar(nsIFile* greOmni, nsIFile* appOmni)
  1234. {
  1235. mozilla::Omnijar::Init(greOmni, appOmni);
  1236. }
  1237. nsresult
  1238. XRE_GetBinaryPath(const char* argv0, nsIFile* *aResult)
  1239. {
  1240. return mozilla::BinaryPath::GetFile(argv0, aResult);
  1241. }
  1242. #ifdef XP_WIN
  1243. #include "nsWindowsRestart.cpp"
  1244. #include <shellapi.h>
  1245. typedef BOOL (WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
  1246. #endif
  1247. // If aBlankCommandLine is true, then the application will be launched with a
  1248. // blank command line instead of being launched with the same command line that
  1249. // it was initially started with.
  1250. static nsresult LaunchChild(nsINativeAppSupport* aNative,
  1251. bool aBlankCommandLine = false)
  1252. {
  1253. aNative->Quit(); // release DDE mutex, if we're holding it
  1254. // Restart this process by exec'ing it into the current process
  1255. // if supported by the platform. Otherwise, use NSPR.
  1256. if (aBlankCommandLine) {
  1257. gRestartArgc = 1;
  1258. gRestartArgv[gRestartArgc] = nullptr;
  1259. }
  1260. SaveToEnv("MOZ_LAUNCHED_CHILD=1");
  1261. nsCOMPtr<nsIFile> lf;
  1262. nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
  1263. if (NS_FAILED(rv))
  1264. return rv;
  1265. #if defined(XP_WIN)
  1266. nsAutoString exePath;
  1267. rv = lf->GetPath(exePath);
  1268. if (NS_FAILED(rv))
  1269. return rv;
  1270. if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv))
  1271. return NS_ERROR_FAILURE;
  1272. #else
  1273. nsAutoCString exePath;
  1274. rv = lf->GetNativePath(exePath);
  1275. if (NS_FAILED(rv))
  1276. return rv;
  1277. #if defined(XP_UNIX)
  1278. if (execv(exePath.get(), gRestartArgv) == -1)
  1279. return NS_ERROR_FAILURE;
  1280. #else
  1281. PRProcess* process = PR_CreateProcess(exePath.get(), gRestartArgv,
  1282. nullptr, nullptr);
  1283. if (!process) return NS_ERROR_FAILURE;
  1284. int32_t exitCode;
  1285. PRStatus failed = PR_WaitProcess(process, &exitCode);
  1286. if (failed || exitCode)
  1287. return NS_ERROR_FAILURE;
  1288. #endif // XP_UNIX
  1289. #endif // WP_WIN
  1290. return NS_ERROR_LAUNCHED_CHILD_PROCESS;
  1291. }
  1292. static const char kProfileProperties[] =
  1293. "chrome://mozapps/locale/profile/profileSelection.properties";
  1294. namespace {
  1295. /**
  1296. * This class, instead of a raw nsresult, should be the return type of any
  1297. * function called by SelectProfile that initializes XPCOM.
  1298. */
  1299. class ReturnAbortOnError
  1300. {
  1301. public:
  1302. MOZ_IMPLICIT ReturnAbortOnError(nsresult aRv)
  1303. {
  1304. mRv = ConvertRv(aRv);
  1305. }
  1306. operator nsresult()
  1307. {
  1308. return mRv;
  1309. }
  1310. private:
  1311. inline nsresult
  1312. ConvertRv(nsresult aRv)
  1313. {
  1314. if (NS_SUCCEEDED(aRv) || aRv == NS_ERROR_LAUNCHED_CHILD_PROCESS) {
  1315. return aRv;
  1316. }
  1317. return NS_ERROR_ABORT;
  1318. }
  1319. nsresult mRv;
  1320. };
  1321. } // namespace
  1322. static ReturnAbortOnError
  1323. ProfileLockedDialog(nsIFile* aProfileDir, nsIFile* aProfileLocalDir,
  1324. nsIProfileUnlocker* aUnlocker,
  1325. nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
  1326. {
  1327. nsresult rv;
  1328. ScopedXPCOMStartup xpcom;
  1329. rv = xpcom.Initialize();
  1330. NS_ENSURE_SUCCESS(rv, rv);
  1331. mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
  1332. rv = xpcom.SetWindowCreator(aNative);
  1333. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1334. { //extra scoping is needed so we release these components before xpcom shutdown
  1335. nsCOMPtr<nsIStringBundleService> sbs =
  1336. mozilla::services::GetStringBundleService();
  1337. NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
  1338. nsCOMPtr<nsIStringBundle> sb;
  1339. sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
  1340. NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
  1341. NS_ConvertUTF8toUTF16 appName(gAppData->name);
  1342. const char16_t* params[] = {appName.get(), appName.get()};
  1343. nsXPIDLString killMessage;
  1344. sb->FormatStringFromName(aUnlocker ? u"restartMessageUnlocker"
  1345. : u"restartMessageNoUnlocker",
  1346. params, 2, getter_Copies(killMessage));
  1347. nsXPIDLString killTitle;
  1348. sb->FormatStringFromName(u"restartTitle",
  1349. params, 1, getter_Copies(killTitle));
  1350. if (!killMessage || !killTitle)
  1351. return NS_ERROR_FAILURE;
  1352. nsCOMPtr<nsIPromptService> ps
  1353. (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
  1354. NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
  1355. if (aUnlocker) {
  1356. int32_t button;
  1357. const uint32_t flags =
  1358. (nsIPromptService::BUTTON_TITLE_IS_STRING *
  1359. nsIPromptService::BUTTON_POS_0) +
  1360. (nsIPromptService::BUTTON_TITLE_CANCEL *
  1361. nsIPromptService::BUTTON_POS_1);
  1362. bool checkState = false;
  1363. rv = ps->ConfirmEx(nullptr, killTitle, killMessage, flags,
  1364. killTitle, nullptr, nullptr, nullptr,
  1365. &checkState, &button);
  1366. NS_ENSURE_SUCCESS_LOG(rv, rv);
  1367. if (button == 0) {
  1368. rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);
  1369. if (NS_FAILED(rv)) {
  1370. return rv;
  1371. }
  1372. SaveFileToEnv("XRE_PROFILE_PATH", aProfileDir);
  1373. SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", aProfileLocalDir);
  1374. return LaunchChild(aNative);
  1375. }
  1376. } else {
  1377. rv = ps->Alert(nullptr, killTitle, killMessage);
  1378. NS_ENSURE_SUCCESS_LOG(rv, rv);
  1379. }
  1380. return NS_ERROR_ABORT;
  1381. }
  1382. }
  1383. static nsresult
  1384. ProfileMissingDialog(nsINativeAppSupport* aNative)
  1385. {
  1386. nsresult rv;
  1387. ScopedXPCOMStartup xpcom;
  1388. rv = xpcom.Initialize();
  1389. NS_ENSURE_SUCCESS(rv, rv);
  1390. rv = xpcom.SetWindowCreator(aNative);
  1391. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1392. { //extra scoping is needed so we release these components before xpcom shutdown
  1393. nsCOMPtr<nsIStringBundleService> sbs =
  1394. mozilla::services::GetStringBundleService();
  1395. NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
  1396. nsCOMPtr<nsIStringBundle> sb;
  1397. sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
  1398. NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
  1399. NS_ConvertUTF8toUTF16 appName(gAppData->name);
  1400. const char16_t* params[] = {appName.get(), appName.get()};
  1401. nsXPIDLString missingMessage;
  1402. // profileMissing
  1403. sb->FormatStringFromName(u"profileMissing", params, 2, getter_Copies(missingMessage));
  1404. nsXPIDLString missingTitle;
  1405. sb->FormatStringFromName(u"profileMissingTitle",
  1406. params, 1, getter_Copies(missingTitle));
  1407. if (missingMessage && missingTitle) {
  1408. nsCOMPtr<nsIPromptService> ps
  1409. (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
  1410. NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
  1411. ps->Alert(nullptr, missingTitle, missingMessage);
  1412. }
  1413. return NS_ERROR_ABORT;
  1414. }
  1415. }
  1416. static nsresult
  1417. ProfileLockedDialog(nsIToolkitProfile* aProfile, nsIProfileUnlocker* aUnlocker,
  1418. nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
  1419. {
  1420. nsCOMPtr<nsIFile> profileDir;
  1421. nsresult rv = aProfile->GetRootDir(getter_AddRefs(profileDir));
  1422. if (NS_FAILED(rv)) return rv;
  1423. bool exists;
  1424. profileDir->Exists(&exists);
  1425. if (!exists) {
  1426. return ProfileMissingDialog(aNative);
  1427. }
  1428. nsCOMPtr<nsIFile> profileLocalDir;
  1429. rv = aProfile->GetLocalDir(getter_AddRefs(profileLocalDir));
  1430. if (NS_FAILED(rv)) return rv;
  1431. return ProfileLockedDialog(profileDir, profileLocalDir, aUnlocker, aNative,
  1432. aResult);
  1433. }
  1434. static const char kProfileManagerURL[] =
  1435. "chrome://mozapps/content/profile/profileSelection.xul";
  1436. static ReturnAbortOnError
  1437. ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
  1438. nsINativeAppSupport* aNative)
  1439. {
  1440. if (!CanShowProfileManager()) {
  1441. return NS_ERROR_NOT_IMPLEMENTED;
  1442. }
  1443. nsresult rv;
  1444. nsCOMPtr<nsIFile> profD, profLD;
  1445. char16_t* profileNamePtr;
  1446. nsAutoCString profileName;
  1447. {
  1448. ScopedXPCOMStartup xpcom;
  1449. rv = xpcom.Initialize();
  1450. NS_ENSURE_SUCCESS(rv, rv);
  1451. // Initialize the graphics prefs, some of the paths need them before
  1452. // any other graphics is initialized (e.g., showing the profile chooser.)
  1453. gfxPrefs::GetSingleton();
  1454. rv = xpcom.SetWindowCreator(aNative);
  1455. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  1456. #ifdef XP_WIN
  1457. // we don't have to wait here because profile manager window will pump
  1458. // and DDE message will be handled
  1459. ProcessDDE(aNative, false);
  1460. #endif
  1461. { //extra scoping is needed so we release these components before xpcom shutdown
  1462. nsCOMPtr<nsIWindowWatcher> windowWatcher
  1463. (do_GetService(NS_WINDOWWATCHER_CONTRACTID));
  1464. nsCOMPtr<nsIDialogParamBlock> ioParamBlock
  1465. (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID));
  1466. nsCOMPtr<nsIMutableArray> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID));
  1467. NS_ENSURE_TRUE(windowWatcher && ioParamBlock && dlgArray, NS_ERROR_FAILURE);
  1468. ioParamBlock->SetObjects(dlgArray);
  1469. nsCOMPtr<nsIAppStartup> appStartup
  1470. (do_GetService(NS_APPSTARTUP_CONTRACTID));
  1471. NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
  1472. nsCOMPtr<mozIDOMWindowProxy> newWindow;
  1473. rv = windowWatcher->OpenWindow(nullptr,
  1474. kProfileManagerURL,
  1475. "_blank",
  1476. "centerscreen,chrome,modal,titlebar",
  1477. ioParamBlock,
  1478. getter_AddRefs(newWindow));
  1479. NS_ENSURE_SUCCESS_LOG(rv, rv);
  1480. aProfileSvc->Flush();
  1481. int32_t dialogConfirmed;
  1482. rv = ioParamBlock->GetInt(0, &dialogConfirmed);
  1483. if (NS_FAILED(rv) || dialogConfirmed == 0) return NS_ERROR_ABORT;
  1484. nsCOMPtr<nsIProfileLock> lock;
  1485. rv = dlgArray->QueryElementAt(0, NS_GET_IID(nsIProfileLock),
  1486. getter_AddRefs(lock));
  1487. NS_ENSURE_SUCCESS_LOG(rv, rv);
  1488. rv = lock->GetDirectory(getter_AddRefs(profD));
  1489. NS_ENSURE_SUCCESS(rv, rv);
  1490. rv = lock->GetLocalDirectory(getter_AddRefs(profLD));
  1491. NS_ENSURE_SUCCESS(rv, rv);
  1492. rv = ioParamBlock->GetString(0, &profileNamePtr);
  1493. NS_ENSURE_SUCCESS(rv, rv);
  1494. CopyUTF16toUTF8(profileNamePtr, profileName);
  1495. free(profileNamePtr);
  1496. lock->Unlock();
  1497. }
  1498. }
  1499. SaveFileToEnv("XRE_PROFILE_PATH", profD);
  1500. SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
  1501. SaveWordToEnv("XRE_PROFILE_NAME", profileName);
  1502. bool offline = false;
  1503. aProfileSvc->GetStartOffline(&offline);
  1504. if (offline) {
  1505. SaveToEnv("XRE_START_OFFLINE=1");
  1506. }
  1507. return LaunchChild(aNative);
  1508. }
  1509. /**
  1510. * Get the currently running profile using its root directory.
  1511. *
  1512. * @param aProfileSvc The profile service
  1513. * @param aCurrentProfileRoot The root directory of the current profile.
  1514. * @param aProfile Out-param that returns the profile object.
  1515. * @return an error if aCurrentProfileRoot is not found
  1516. */
  1517. static nsresult
  1518. GetCurrentProfile(nsIToolkitProfileService* aProfileSvc,
  1519. nsIFile* aCurrentProfileRoot,
  1520. nsIToolkitProfile** aProfile)
  1521. {
  1522. NS_ENSURE_ARG_POINTER(aProfileSvc);
  1523. NS_ENSURE_ARG_POINTER(aProfile);
  1524. nsCOMPtr<nsISimpleEnumerator> profiles;
  1525. nsresult rv = aProfileSvc->GetProfiles(getter_AddRefs(profiles));
  1526. if (NS_FAILED(rv))
  1527. return rv;
  1528. bool foundMatchingProfile = false;
  1529. nsCOMPtr<nsISupports> supports;
  1530. rv = profiles->GetNext(getter_AddRefs(supports));
  1531. while (NS_SUCCEEDED(rv)) {
  1532. nsCOMPtr<nsIToolkitProfile> profile = do_QueryInterface(supports);
  1533. nsCOMPtr<nsIFile> profileRoot;
  1534. profile->GetRootDir(getter_AddRefs(profileRoot));
  1535. profileRoot->Equals(aCurrentProfileRoot, &foundMatchingProfile);
  1536. if (foundMatchingProfile) {
  1537. profile.forget(aProfile);
  1538. return NS_OK;
  1539. }
  1540. rv = profiles->GetNext(getter_AddRefs(supports));
  1541. }
  1542. return rv;
  1543. }
  1544. static bool gDoMigration = false;
  1545. static bool gDoProfileReset = false;
  1546. static nsAutoCString gResetOldProfileName;
  1547. // Pick a profile. We need to end up with a profile lock.
  1548. //
  1549. // 1) check for --profile <path>
  1550. // 2) check for -P <name>
  1551. // 3) check for --ProfileManager
  1552. // 4) use the default profile, if there is one
  1553. // 5) if there are *no* profiles, set up profile-migration
  1554. // 6) display the profile-manager UI
  1555. static nsresult
  1556. SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative,
  1557. bool* aStartOffline, nsACString* aProfileName)
  1558. {
  1559. StartupTimeline::Record(StartupTimeline::SELECT_PROFILE);
  1560. nsresult rv;
  1561. ArgResult ar;
  1562. const char* arg;
  1563. *aResult = nullptr;
  1564. *aStartOffline = false;
  1565. ar = CheckArg("offline", true);
  1566. if (ar == ARG_BAD) {
  1567. PR_fprintf(PR_STDERR, "Error: argument --offline is invalid when argument --osint is specified\n");
  1568. return NS_ERROR_FAILURE;
  1569. }
  1570. if (ar || EnvHasValue("XRE_START_OFFLINE"))
  1571. *aStartOffline = true;
  1572. if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
  1573. gDoProfileReset = true;
  1574. gDoMigration = true;
  1575. SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
  1576. }
  1577. // reset-profile and migration args need to be checked before any profiles are chosen below.
  1578. ar = CheckArg("reset-profile", true);
  1579. if (ar == ARG_BAD) {
  1580. PR_fprintf(PR_STDERR, "Error: argument --reset-profile is invalid when argument --osint is specified\n");
  1581. return NS_ERROR_FAILURE;
  1582. } else if (ar == ARG_FOUND) {
  1583. gDoProfileReset = true;
  1584. }
  1585. ar = CheckArg("migration", true);
  1586. if (ar == ARG_BAD) {
  1587. PR_fprintf(PR_STDERR, "Error: argument --migration is invalid when argument --osint is specified\n");
  1588. return NS_ERROR_FAILURE;
  1589. } else if (ar == ARG_FOUND) {
  1590. gDoMigration = true;
  1591. }
  1592. nsCOMPtr<nsIFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
  1593. if (lf) {
  1594. nsCOMPtr<nsIFile> localDir =
  1595. GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
  1596. if (!localDir) {
  1597. localDir = lf;
  1598. }
  1599. arg = PR_GetEnv("XRE_PROFILE_NAME");
  1600. if (arg && *arg && aProfileName) {
  1601. aProfileName->Assign(nsDependentCString(arg));
  1602. if (gDoProfileReset) {
  1603. gResetOldProfileName.Assign(*aProfileName);
  1604. }
  1605. }
  1606. // Clear out flags that we handled (or should have handled!) last startup.
  1607. const char *dummy;
  1608. CheckArg("p", false, &dummy);
  1609. CheckArg("profile", false, &dummy);
  1610. CheckArg("profilemanager");
  1611. if (gDoProfileReset) {
  1612. // If we're resetting a profile, create a new one and use it to startup.
  1613. nsCOMPtr<nsIToolkitProfile> newProfile;
  1614. rv = CreateResetProfile(aProfileSvc, gResetOldProfileName, getter_AddRefs(newProfile));
  1615. if (NS_SUCCEEDED(rv)) {
  1616. rv = newProfile->GetRootDir(getter_AddRefs(lf));
  1617. NS_ENSURE_SUCCESS(rv, rv);
  1618. SaveFileToEnv("XRE_PROFILE_PATH", lf);
  1619. rv = newProfile->GetLocalDir(getter_AddRefs(localDir));
  1620. NS_ENSURE_SUCCESS(rv, rv);
  1621. SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", localDir);
  1622. rv = newProfile->GetName(*aProfileName);
  1623. if (NS_FAILED(rv))
  1624. aProfileName->Truncate(0);
  1625. SaveWordToEnv("XRE_PROFILE_NAME", *aProfileName);
  1626. } else {
  1627. NS_WARNING("Profile reset failed.");
  1628. gDoProfileReset = false;
  1629. }
  1630. }
  1631. return NS_LockProfilePath(lf, localDir, nullptr, aResult);
  1632. }
  1633. ar = CheckArg("profile", true, &arg);
  1634. if (ar == ARG_BAD) {
  1635. PR_fprintf(PR_STDERR, "Error: argument --profile requires a path\n");
  1636. return NS_ERROR_FAILURE;
  1637. }
  1638. if (ar) {
  1639. if (gDoProfileReset) {
  1640. NS_WARNING("Profile reset is not supported in conjunction with --profile.");
  1641. gDoProfileReset = false;
  1642. }
  1643. nsCOMPtr<nsIFile> lf;
  1644. rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf));
  1645. NS_ENSURE_SUCCESS(rv, rv);
  1646. nsCOMPtr<nsIProfileUnlocker> unlocker;
  1647. // Check if the profile path exists and it's a directory.
  1648. bool exists;
  1649. lf->Exists(&exists);
  1650. if (!exists) {
  1651. rv = lf->Create(nsIFile::DIRECTORY_TYPE, 0700);
  1652. NS_ENSURE_SUCCESS(rv, rv);
  1653. }
  1654. // If a profile path is specified directory on the command line, then
  1655. // assume that the temp directory is the same as the given directory.
  1656. rv = NS_LockProfilePath(lf, lf, getter_AddRefs(unlocker), aResult);
  1657. if (NS_SUCCEEDED(rv))
  1658. return rv;
  1659. return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
  1660. }
  1661. ar = CheckArg("createprofile", true, &arg);
  1662. if (ar == ARG_BAD) {
  1663. PR_fprintf(PR_STDERR, "Error: argument --createprofile requires a profile name\n");
  1664. return NS_ERROR_FAILURE;
  1665. }
  1666. if (ar) {
  1667. nsCOMPtr<nsIToolkitProfile> profile;
  1668. const char* delim = strchr(arg, ' ');
  1669. if (delim) {
  1670. nsCOMPtr<nsIFile> lf;
  1671. rv = NS_NewNativeLocalFile(nsDependentCString(delim + 1),
  1672. true, getter_AddRefs(lf));
  1673. if (NS_FAILED(rv)) {
  1674. PR_fprintf(PR_STDERR, "Error: profile path not valid.\n");
  1675. return rv;
  1676. }
  1677. // As with --profile, assume that the given path will be used for the
  1678. // main profile directory.
  1679. rv = aProfileSvc->CreateProfile(lf, nsDependentCSubstring(arg, delim),
  1680. getter_AddRefs(profile));
  1681. } else {
  1682. rv = aProfileSvc->CreateProfile(nullptr, nsDependentCString(arg),
  1683. getter_AddRefs(profile));
  1684. }
  1685. // Some pathological arguments can make it this far
  1686. if (NS_FAILED(rv)) {
  1687. PR_fprintf(PR_STDERR, "Error creating profile.\n");
  1688. return rv;
  1689. }
  1690. rv = NS_ERROR_ABORT;
  1691. aProfileSvc->Flush();
  1692. // XXXben need to ensure prefs.js exists here so the tinderboxes will
  1693. // not go orange.
  1694. nsCOMPtr<nsIFile> prefsJSFile;
  1695. profile->GetRootDir(getter_AddRefs(prefsJSFile));
  1696. prefsJSFile->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
  1697. nsAutoCString pathStr;
  1698. prefsJSFile->GetNativePath(pathStr);
  1699. PR_fprintf(PR_STDERR, "Success: created profile '%s' at '%s'\n", arg, pathStr.get());
  1700. bool exists;
  1701. prefsJSFile->Exists(&exists);
  1702. if (!exists) {
  1703. // Ignore any errors; we're about to return NS_ERROR_ABORT anyway.
  1704. Unused << prefsJSFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
  1705. }
  1706. // XXXdarin perhaps 0600 would be better?
  1707. return rv;
  1708. }
  1709. uint32_t count;
  1710. rv = aProfileSvc->GetProfileCount(&count);
  1711. NS_ENSURE_SUCCESS(rv, rv);
  1712. ar = CheckArg("p", false, &arg);
  1713. if (ar == ARG_BAD) {
  1714. ar = CheckArg("osint");
  1715. if (ar == ARG_FOUND) {
  1716. PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument --osint is specified\n");
  1717. return NS_ERROR_FAILURE;
  1718. }
  1719. if (CanShowProfileManager()) {
  1720. return ShowProfileManager(aProfileSvc, aNative);
  1721. }
  1722. }
  1723. if (ar) {
  1724. ar = CheckArg("osint");
  1725. if (ar == ARG_FOUND) {
  1726. PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument --osint is specified\n");
  1727. return NS_ERROR_FAILURE;
  1728. }
  1729. nsCOMPtr<nsIToolkitProfile> profile;
  1730. rv = aProfileSvc->GetProfileByName(nsDependentCString(arg),
  1731. getter_AddRefs(profile));
  1732. if (NS_SUCCEEDED(rv)) {
  1733. if (gDoProfileReset) {
  1734. {
  1735. // Check that the source profile is not in use by temporarily acquiring its lock.
  1736. nsIProfileLock* tempProfileLock;
  1737. nsCOMPtr<nsIProfileUnlocker> unlocker;
  1738. rv = profile->Lock(getter_AddRefs(unlocker), &tempProfileLock);
  1739. if (NS_FAILED(rv))
  1740. return ProfileLockedDialog(profile, unlocker, aNative, &tempProfileLock);
  1741. }
  1742. nsresult gotName = profile->GetName(gResetOldProfileName);
  1743. if (NS_SUCCEEDED(gotName)) {
  1744. nsCOMPtr<nsIToolkitProfile> newProfile;
  1745. rv = CreateResetProfile(aProfileSvc, gResetOldProfileName, getter_AddRefs(newProfile));
  1746. if (NS_FAILED(rv)) {
  1747. NS_WARNING("Failed to create a profile to reset to.");
  1748. gDoProfileReset = false;
  1749. } else {
  1750. profile = newProfile;
  1751. }
  1752. } else {
  1753. NS_WARNING("Failed to get the name of the profile we're resetting, so aborting reset.");
  1754. gResetOldProfileName.Truncate(0);
  1755. gDoProfileReset = false;
  1756. }
  1757. }
  1758. nsCOMPtr<nsIProfileUnlocker> unlocker;
  1759. rv = profile->Lock(getter_AddRefs(unlocker), aResult);
  1760. if (NS_SUCCEEDED(rv)) {
  1761. if (aProfileName)
  1762. aProfileName->Assign(nsDependentCString(arg));
  1763. return NS_OK;
  1764. }
  1765. return ProfileLockedDialog(profile, unlocker, aNative, aResult);
  1766. }
  1767. if (CanShowProfileManager()) {
  1768. return ShowProfileManager(aProfileSvc, aNative);
  1769. }
  1770. }
  1771. ar = CheckArg("profilemanager", true);
  1772. if (ar == ARG_BAD) {
  1773. PR_fprintf(PR_STDERR, "Error: argument --profilemanager is invalid when argument --osint is specified\n");
  1774. return NS_ERROR_FAILURE;
  1775. } else if (ar == ARG_FOUND && CanShowProfileManager()) {
  1776. return ShowProfileManager(aProfileSvc, aNative);
  1777. }
  1778. // Dev edition leftovers:
  1779. // If the only existing profile is the dev-edition-profile,
  1780. // then no valid profiles were found.
  1781. if (count == 1) {
  1782. nsCOMPtr<nsIToolkitProfile> deProfile;
  1783. // GetSelectedProfile will auto-select the only profile if there's just one
  1784. aProfileSvc->GetSelectedProfile(getter_AddRefs(deProfile));
  1785. nsAutoCString profileName;
  1786. deProfile->GetName(profileName);
  1787. if (profileName.EqualsLiteral("dev-edition-default")) {
  1788. count = 0;
  1789. }
  1790. }
  1791. if (!count) {
  1792. gDoMigration = true;
  1793. gDoProfileReset = false;
  1794. // create a default profile
  1795. nsCOMPtr<nsIToolkitProfile> profile;
  1796. nsresult rv = aProfileSvc->CreateProfile(nullptr, // choose a default dir for us
  1797. NS_LITERAL_CSTRING("default"),
  1798. getter_AddRefs(profile));
  1799. if (NS_SUCCEEDED(rv)) {
  1800. aProfileSvc->SetDefaultProfile(profile);
  1801. aProfileSvc->Flush();
  1802. rv = profile->Lock(nullptr, aResult);
  1803. if (NS_SUCCEEDED(rv)) {
  1804. if (aProfileName)
  1805. aProfileName->AssignLiteral("default");
  1806. return NS_OK;
  1807. }
  1808. }
  1809. }
  1810. bool useDefault = true;
  1811. if (count > 1 && CanShowProfileManager()) {
  1812. aProfileSvc->GetStartWithLastProfile(&useDefault);
  1813. }
  1814. if (useDefault) {
  1815. nsCOMPtr<nsIToolkitProfile> profile;
  1816. // GetSelectedProfile will auto-select the only profile if there's just one
  1817. aProfileSvc->GetSelectedProfile(getter_AddRefs(profile));
  1818. if (profile) {
  1819. // If we're resetting a profile, create a new one and use it to startup.
  1820. if (gDoProfileReset) {
  1821. {
  1822. // Check that the source profile is not in use by temporarily acquiring its lock.
  1823. nsIProfileLock* tempProfileLock;
  1824. nsCOMPtr<nsIProfileUnlocker> unlocker;
  1825. rv = profile->Lock(getter_AddRefs(unlocker), &tempProfileLock);
  1826. if (NS_FAILED(rv))
  1827. return ProfileLockedDialog(profile, unlocker, aNative, &tempProfileLock);
  1828. }
  1829. nsresult gotName = profile->GetName(gResetOldProfileName);
  1830. if (NS_SUCCEEDED(gotName)) {
  1831. nsCOMPtr<nsIToolkitProfile> newProfile;
  1832. rv = CreateResetProfile(aProfileSvc, gResetOldProfileName, getter_AddRefs(newProfile));
  1833. if (NS_FAILED(rv)) {
  1834. NS_WARNING("Failed to create a profile to reset to.");
  1835. gDoProfileReset = false;
  1836. }
  1837. else {
  1838. profile = newProfile;
  1839. }
  1840. }
  1841. else {
  1842. NS_WARNING("Failed to get the name of the profile we're resetting, so aborting reset.");
  1843. gResetOldProfileName.Truncate(0);
  1844. gDoProfileReset = false;
  1845. }
  1846. }
  1847. // If you close Firefox and very quickly reopen it, the old Firefox may
  1848. // still be closing down. Rather than immediately showing the
  1849. // "Firefox is running but is not responding" message, we spend a few
  1850. // seconds retrying first.
  1851. static const int kLockRetrySeconds = 5;
  1852. static const int kLockRetrySleepMS = 100;
  1853. nsCOMPtr<nsIProfileUnlocker> unlocker;
  1854. const TimeStamp start = TimeStamp::Now();
  1855. do {
  1856. rv = profile->Lock(getter_AddRefs(unlocker), aResult);
  1857. if (NS_SUCCEEDED(rv)) {
  1858. StartupTimeline::Record(StartupTimeline::AFTER_PROFILE_LOCKED);
  1859. // Try to grab the profile name.
  1860. if (aProfileName) {
  1861. rv = profile->GetName(*aProfileName);
  1862. if (NS_FAILED(rv))
  1863. aProfileName->Truncate(0);
  1864. }
  1865. return NS_OK;
  1866. }
  1867. PR_Sleep(kLockRetrySleepMS);
  1868. } while (TimeStamp::Now() - start < TimeDuration::FromSeconds(kLockRetrySeconds));
  1869. return ProfileLockedDialog(profile, unlocker, aNative, aResult);
  1870. }
  1871. }
  1872. if (!CanShowProfileManager()) {
  1873. return NS_ERROR_FAILURE;
  1874. }
  1875. return ShowProfileManager(aProfileSvc, aNative);
  1876. }
  1877. /**
  1878. * Checks the compatibility.ini file to see if we have updated our application
  1879. * or otherwise invalidated our caches. If the application has been updated,
  1880. * we return false; otherwise, we return true. We also write the status
  1881. * of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
  1882. * is always invalid if the application has been updated.
  1883. */
  1884. static bool
  1885. CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
  1886. const nsCString& aOSABI, nsIFile* aXULRunnerDir,
  1887. nsIFile* aAppDir, nsIFile* aFlagFile,
  1888. bool* aCachesOK)
  1889. {
  1890. *aCachesOK = false;
  1891. nsCOMPtr<nsIFile> file;
  1892. aProfileDir->Clone(getter_AddRefs(file));
  1893. if (!file)
  1894. return false;
  1895. file->AppendNative(FILE_COMPATIBILITY_INFO);
  1896. nsINIParser parser;
  1897. nsresult rv = parser.Init(file);
  1898. if (NS_FAILED(rv))
  1899. return false;
  1900. nsAutoCString buf;
  1901. rv = parser.GetString("Compatibility", "LastVersion", buf);
  1902. if (NS_FAILED(rv) || !aVersion.Equals(buf))
  1903. return false;
  1904. rv = parser.GetString("Compatibility", "LastOSABI", buf);
  1905. if (NS_FAILED(rv) || !aOSABI.Equals(buf))
  1906. return false;
  1907. rv = parser.GetString("Compatibility", "LastPlatformDir", buf);
  1908. if (NS_FAILED(rv))
  1909. return false;
  1910. nsCOMPtr<nsIFile> lf;
  1911. rv = NS_NewNativeLocalFile(buf, false,
  1912. getter_AddRefs(lf));
  1913. if (NS_FAILED(rv))
  1914. return false;
  1915. bool eq;
  1916. rv = lf->Equals(aXULRunnerDir, &eq);
  1917. if (NS_FAILED(rv) || !eq)
  1918. return false;
  1919. if (aAppDir) {
  1920. rv = parser.GetString("Compatibility", "LastAppDir", buf);
  1921. if (NS_FAILED(rv))
  1922. return false;
  1923. rv = NS_NewNativeLocalFile(buf, false,
  1924. getter_AddRefs(lf));
  1925. if (NS_FAILED(rv))
  1926. return false;
  1927. rv = lf->Equals(aAppDir, &eq);
  1928. if (NS_FAILED(rv) || !eq)
  1929. return false;
  1930. }
  1931. // If we see this flag, caches are invalid.
  1932. rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
  1933. *aCachesOK = (NS_FAILED(rv) || !buf.EqualsLiteral("1"));
  1934. bool purgeCaches = false;
  1935. if (aFlagFile) {
  1936. aFlagFile->Exists(&purgeCaches);
  1937. }
  1938. *aCachesOK = !purgeCaches && *aCachesOK;
  1939. return true;
  1940. }
  1941. static void BuildVersion(nsCString &aBuf)
  1942. {
  1943. aBuf.Assign(gAppData->version);
  1944. aBuf.Append('_');
  1945. aBuf.Append(gAppData->buildID);
  1946. aBuf.Append('/');
  1947. aBuf.Append(gToolkitBuildID);
  1948. }
  1949. static void
  1950. WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
  1951. const nsCString& aOSABI, nsIFile* aXULRunnerDir,
  1952. nsIFile* aAppDir, bool invalidateCache)
  1953. {
  1954. nsCOMPtr<nsIFile> file;
  1955. aProfileDir->Clone(getter_AddRefs(file));
  1956. if (!file)
  1957. return;
  1958. file->AppendNative(FILE_COMPATIBILITY_INFO);
  1959. nsAutoCString platformDir;
  1960. aXULRunnerDir->GetNativePath(platformDir);
  1961. nsAutoCString appDir;
  1962. if (aAppDir)
  1963. aAppDir->GetNativePath(appDir);
  1964. PRFileDesc *fd;
  1965. nsresult rv =
  1966. file->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
  1967. if (NS_FAILED(rv)) {
  1968. NS_ERROR("could not create output stream");
  1969. return;
  1970. }
  1971. static const char kHeader[] = "[Compatibility]" NS_LINEBREAK
  1972. "LastVersion=";
  1973. PR_Write(fd, kHeader, sizeof(kHeader) - 1);
  1974. PR_Write(fd, aVersion.get(), aVersion.Length());
  1975. static const char kOSABIHeader[] = NS_LINEBREAK "LastOSABI=";
  1976. PR_Write(fd, kOSABIHeader, sizeof(kOSABIHeader) - 1);
  1977. PR_Write(fd, aOSABI.get(), aOSABI.Length());
  1978. static const char kPlatformDirHeader[] = NS_LINEBREAK "LastPlatformDir=";
  1979. PR_Write(fd, kPlatformDirHeader, sizeof(kPlatformDirHeader) - 1);
  1980. PR_Write(fd, platformDir.get(), platformDir.Length());
  1981. static const char kAppDirHeader[] = NS_LINEBREAK "LastAppDir=";
  1982. if (aAppDir) {
  1983. PR_Write(fd, kAppDirHeader, sizeof(kAppDirHeader) - 1);
  1984. PR_Write(fd, appDir.get(), appDir.Length());
  1985. }
  1986. static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1";
  1987. if (invalidateCache)
  1988. PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
  1989. static const char kNL[] = NS_LINEBREAK;
  1990. PR_Write(fd, kNL, sizeof(kNL) - 1);
  1991. PR_Close(fd);
  1992. }
  1993. /**
  1994. * Returns true if the startup cache file was successfully removed.
  1995. * Returns false if file->Clone fails at any point (OOM) or if unable
  1996. * to remove the startup cache file. Note in particular the return value
  1997. * is unaffected by a failure to remove extensions.ini
  1998. */
  1999. static bool
  2000. RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfileDir,
  2001. bool aRemoveEMFiles)
  2002. {
  2003. nsCOMPtr<nsIFile> file;
  2004. aProfileDir->Clone(getter_AddRefs(file));
  2005. if (!file)
  2006. return false;
  2007. if (aRemoveEMFiles) {
  2008. file->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
  2009. file->Remove(false);
  2010. }
  2011. aLocalProfileDir->Clone(getter_AddRefs(file));
  2012. if (!file)
  2013. return false;
  2014. #if defined(XP_UNIX)
  2015. #define PLATFORM_FASL_SUFFIX ".mfasl"
  2016. #elif defined(XP_WIN)
  2017. #define PLATFORM_FASL_SUFFIX ".mfl"
  2018. #endif
  2019. file->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX));
  2020. file->Remove(false);
  2021. file->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX));
  2022. file->Remove(false);
  2023. file->SetNativeLeafName(NS_LITERAL_CSTRING("startupCache"));
  2024. nsresult rv = file->Remove(true);
  2025. return NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
  2026. }
  2027. // To support application initiated restart via nsIAppStartup.quit, we
  2028. // need to save various environment variables, and then restore them
  2029. // before re-launching the application.
  2030. static struct SavedVar {
  2031. const char *name;
  2032. char *value;
  2033. } gSavedVars[] = {
  2034. {"XUL_APP_FILE", nullptr}
  2035. };
  2036. static void SaveStateForAppInitiatedRestart()
  2037. {
  2038. for (size_t i = 0; i < ArrayLength(gSavedVars); ++i) {
  2039. const char *s = PR_GetEnv(gSavedVars[i].name);
  2040. if (s)
  2041. gSavedVars[i].value = PR_smprintf("%s=%s", gSavedVars[i].name, s);
  2042. }
  2043. }
  2044. static void RestoreStateForAppInitiatedRestart()
  2045. {
  2046. for (size_t i = 0; i < ArrayLength(gSavedVars); ++i) {
  2047. if (gSavedVars[i].value)
  2048. PR_SetEnv(gSavedVars[i].value);
  2049. }
  2050. }
  2051. const nsXREAppData* gAppData = nullptr;
  2052. #ifdef MOZ_WIDGET_GTK
  2053. static void MOZ_gdk_display_close(GdkDisplay *display)
  2054. {
  2055. #if CLEANUP_MEMORY
  2056. // XXX wallpaper for bug 417163: don't close the Display if we're using the
  2057. // Qt theme because we crash (in Qt code) when using jemalloc.
  2058. bool skip_display_close = false;
  2059. GtkSettings* settings =
  2060. gtk_settings_get_for_screen(gdk_display_get_default_screen(display));
  2061. gchar *theme_name;
  2062. g_object_get(settings, "gtk-theme-name", &theme_name, nullptr);
  2063. if (theme_name) {
  2064. skip_display_close = strcmp(theme_name, "Qt") == 0;
  2065. if (skip_display_close)
  2066. NS_WARNING("wallpaper bug 417163 for Qt theme");
  2067. g_free(theme_name);
  2068. }
  2069. #if (MOZ_WIDGET_GTK == 3)
  2070. // A workaround for https://bugzilla.gnome.org/show_bug.cgi?id=703257
  2071. if (gtk_check_version(3,9,8) != NULL)
  2072. skip_display_close = true;
  2073. #endif
  2074. // Get a (new) Pango context that holds a reference to the fontmap that
  2075. // GTK has been using. gdk_pango_context_get() must be called while GTK
  2076. // has a default display.
  2077. PangoContext *pangoContext = gdk_pango_context_get();
  2078. bool buggyCairoShutdown = cairo_version() < CAIRO_VERSION_ENCODE(1, 4, 0);
  2079. if (!buggyCairoShutdown) {
  2080. // We should shut down GDK before we shut down libraries it depends on
  2081. // like Pango and cairo. But if cairo shutdown is buggy, we should
  2082. // shut down cairo first otherwise it may crash because of dangling
  2083. // references to Display objects (see bug 469831).
  2084. if (!skip_display_close)
  2085. gdk_display_close(display);
  2086. }
  2087. // Clean up PangoCairo's default fontmap.
  2088. // This pango_fc_font_map_shutdown call (and the associated code to
  2089. // get the font map) really shouldn't be needed anymore, except that
  2090. // it's needed to avoid having cairo_debug_reset_static_data fatally
  2091. // assert if we've leaked other things that hold on to the fontmap,
  2092. // which is something that currently happens in mochitest-plugins.
  2093. // Even if it didn't happen in mochitest-plugins, we probably want to
  2094. // avoid the crash-on-leak problem since it makes it harder to use
  2095. // many of our leak tools to debug leaks.
  2096. // This doesn't take a reference.
  2097. PangoFontMap *fontmap = pango_context_get_font_map(pangoContext);
  2098. // Do some shutdown of the fontmap, which releases the fonts, clearing a
  2099. // bunch of circular references from the fontmap through the fonts back to
  2100. // itself. The shutdown that this does is much less than what's done by
  2101. // the fontmap's finalize, though.
  2102. if (PANGO_IS_FC_FONT_MAP(fontmap))
  2103. pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(fontmap));
  2104. g_object_unref(pangoContext);
  2105. // Tell PangoCairo to release its default fontmap.
  2106. pango_cairo_font_map_set_default(nullptr);
  2107. // cairo_debug_reset_static_data() is prototyped through cairo.h included
  2108. // by gtk.h.
  2109. #ifdef cairo_debug_reset_static_data
  2110. #error "Looks like we're including Mozilla's cairo instead of system cairo"
  2111. #endif
  2112. cairo_debug_reset_static_data();
  2113. // FIXME: Do we need to call this in non-GTK2 cases as well?
  2114. FcFini();
  2115. if (buggyCairoShutdown) {
  2116. if (!skip_display_close)
  2117. gdk_display_close(display);
  2118. }
  2119. #else // not CLEANUP_MEMORY
  2120. // Don't do anything to avoid running into driver bugs under XCloseDisplay().
  2121. // See bug 973192.
  2122. (void) display;
  2123. #endif
  2124. }
  2125. static const char* detectDisplay(void)
  2126. {
  2127. bool tryX11 = false;
  2128. bool tryWayland = false;
  2129. bool tryBroadway = false;
  2130. // Honor user backend selection
  2131. const char *backend = PR_GetEnv("GDK_BACKEND");
  2132. if (!backend || strstr(backend, "*")) {
  2133. // Try all backends
  2134. tryX11 = true;
  2135. tryWayland = true;
  2136. tryBroadway = true;
  2137. } else if (backend) {
  2138. if (strstr(backend, "x11"))
  2139. tryX11 = true;
  2140. if (strstr(backend, "wayland"))
  2141. tryWayland = true;
  2142. if (strstr(backend, "broadway"))
  2143. tryBroadway = true;
  2144. }
  2145. const char *display_name;
  2146. if (tryX11 && (display_name = PR_GetEnv("DISPLAY"))) {
  2147. return display_name;
  2148. } else if (tryWayland && (display_name = PR_GetEnv("WAYLAND_DISPLAY"))) {
  2149. return display_name;
  2150. } else if (tryBroadway && (display_name = PR_GetEnv("BROADWAY_DISPLAY"))) {
  2151. return display_name;
  2152. }
  2153. PR_fprintf(PR_STDERR, "Error: GDK_BACKEND does not match available displays\n");
  2154. return nullptr;
  2155. }
  2156. #endif // MOZ_WIDGET_GTK
  2157. /**
  2158. * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
  2159. * the process and use it to determine whether the application defines its own
  2160. * memory allocator or not.
  2161. *
  2162. * Since most applications (e.g. Firefox and Thunderbird) don't use any special
  2163. * allocators and therefore don't define this symbol, NSPR must search the
  2164. * entire process, which reduces startup performance.
  2165. *
  2166. * By defining the symbol here, we can avoid the wasted lookup and hopefully
  2167. * improve startup performance.
  2168. */
  2169. NS_VISIBILITY_DEFAULT PRBool nspr_use_zone_allocator = PR_FALSE;
  2170. #ifdef CAIRO_HAS_DWRITE_FONT
  2171. #include <dwrite.h>
  2172. #include "nsWindowsHelpers.h"
  2173. #ifdef DEBUG_DWRITE_STARTUP
  2174. #define LOGREGISTRY(msg) LogRegistryEvent(msg)
  2175. // for use when monitoring process
  2176. static void LogRegistryEvent(const wchar_t *msg)
  2177. {
  2178. HKEY dummyKey;
  2179. HRESULT hr;
  2180. wchar_t buf[512];
  2181. wsprintf(buf, L" log %s", msg);
  2182. hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey);
  2183. if (SUCCEEDED(hr)) {
  2184. RegCloseKey(dummyKey);
  2185. }
  2186. }
  2187. #else
  2188. #define LOGREGISTRY(msg)
  2189. #endif
  2190. static DWORD WINAPI InitDwriteBG(LPVOID lpdwThreadParam)
  2191. {
  2192. SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);
  2193. LOGREGISTRY(L"loading dwrite.dll");
  2194. HMODULE dwdll = LoadLibrarySystem32(L"dwrite.dll");
  2195. if (dwdll) {
  2196. decltype(DWriteCreateFactory)* createDWriteFactory = (decltype(DWriteCreateFactory)*)
  2197. GetProcAddress(dwdll, "DWriteCreateFactory");
  2198. if (createDWriteFactory) {
  2199. LOGREGISTRY(L"creating dwrite factory");
  2200. IDWriteFactory *factory;
  2201. HRESULT hr = createDWriteFactory(
  2202. DWRITE_FACTORY_TYPE_SHARED,
  2203. __uuidof(IDWriteFactory),
  2204. reinterpret_cast<IUnknown**>(&factory));
  2205. if (SUCCEEDED(hr)) {
  2206. LOGREGISTRY(L"dwrite factory done");
  2207. factory->Release();
  2208. LOGREGISTRY(L"freed factory");
  2209. } else {
  2210. LOGREGISTRY(L"failed to create factory");
  2211. }
  2212. }
  2213. }
  2214. SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
  2215. return 0;
  2216. }
  2217. #endif
  2218. #ifdef USE_GLX_TEST
  2219. bool fire_glxtest_process();
  2220. #endif
  2221. #include "GeckoProfiler.h"
  2222. // Encapsulates startup and shutdown state for XRE_main
  2223. class XREMain
  2224. {
  2225. public:
  2226. XREMain() :
  2227. mStartOffline(false)
  2228. , mShuttingDown(false)
  2229. #ifdef MOZ_ENABLE_XREMOTE
  2230. , mDisableRemote(false)
  2231. #endif
  2232. #if defined(MOZ_WIDGET_GTK)
  2233. , mGdkDisplay(nullptr)
  2234. #endif
  2235. {};
  2236. ~XREMain() {
  2237. mScopedXPCOM = nullptr;
  2238. mAppData = nullptr;
  2239. }
  2240. int XRE_main(int argc, char* argv[], const nsXREAppData* aAppData);
  2241. int XRE_mainInit(bool* aExitFlag);
  2242. int XRE_mainStartup(bool* aExitFlag);
  2243. nsresult XRE_mainRun();
  2244. nsCOMPtr<nsINativeAppSupport> mNativeApp;
  2245. nsCOMPtr<nsIToolkitProfileService> mProfileSvc;
  2246. nsCOMPtr<nsIFile> mProfD;
  2247. nsCOMPtr<nsIFile> mProfLD;
  2248. nsCOMPtr<nsIProfileLock> mProfileLock;
  2249. #ifdef MOZ_ENABLE_XREMOTE
  2250. nsCOMPtr<nsIRemoteService> mRemoteService;
  2251. nsProfileLock mRemoteLock;
  2252. nsCOMPtr<nsIFile> mRemoteLockDir;
  2253. #endif
  2254. UniquePtr<ScopedXPCOMStartup> mScopedXPCOM;
  2255. nsAutoPtr<mozilla::ScopedAppData> mAppData;
  2256. nsXREDirProvider mDirProvider;
  2257. nsAutoCString mProfileName;
  2258. nsAutoCString mDesktopStartupID;
  2259. bool mStartOffline;
  2260. bool mShuttingDown;
  2261. #ifdef MOZ_ENABLE_XREMOTE
  2262. bool mDisableRemote;
  2263. #endif
  2264. #if defined(MOZ_WIDGET_GTK)
  2265. GdkDisplay* mGdkDisplay;
  2266. #endif
  2267. };
  2268. /*
  2269. * XRE_mainInit - Initial setup and command line parameter processing.
  2270. * Main() will exit early if either return value != 0 or if aExitFlag is
  2271. * true.
  2272. */
  2273. int
  2274. XREMain::XRE_mainInit(bool* aExitFlag)
  2275. {
  2276. if (!aExitFlag)
  2277. return 1;
  2278. *aExitFlag = false;
  2279. atexit(UnexpectedExit);
  2280. auto expectedShutdown = mozilla::MakeScopeExit([&] {
  2281. MozExpectedExit();
  2282. });
  2283. StartupTimeline::Record(StartupTimeline::MAIN);
  2284. if (PR_GetEnv("MOZ_CHAOSMODE")) {
  2285. ChaosFeature feature = ChaosFeature::Any;
  2286. long featureInt = strtol(PR_GetEnv("MOZ_CHAOSMODE"), nullptr, 16);
  2287. if (featureInt) {
  2288. // NOTE: MOZ_CHAOSMODE=0 or a non-hex value maps to Any feature.
  2289. feature = static_cast<ChaosFeature>(featureInt);
  2290. }
  2291. ChaosMode::SetChaosFeature(feature);
  2292. }
  2293. if (ChaosMode::isActive(ChaosFeature::Any)) {
  2294. printf_stderr("*** You are running in chaos test mode. See ChaosMode.h. ***\n");
  2295. }
  2296. nsresult rv;
  2297. ArgResult ar;
  2298. #ifdef DEBUG
  2299. if (PR_GetEnv("XRE_MAIN_BREAK"))
  2300. NS_BREAK();
  2301. #endif
  2302. #ifdef USE_GLX_TEST
  2303. // bug 639842 - it's very important to fire this process BEFORE we set up
  2304. // error handling. indeed, this process is expected to be crashy, and we
  2305. // don't want the user to see its crashes. That's the whole reason for
  2306. // doing this in a separate process.
  2307. //
  2308. // This call will cause a fork and the fork will terminate itself separately
  2309. // from the usual shutdown sequence
  2310. fire_glxtest_process();
  2311. #endif
  2312. SetupErrorHandling(gArgv[0]);
  2313. // Set up environment for NSS database choice
  2314. #ifndef NSS_DISABLE_DBM
  2315. // Allow iteration counts in DBM mode
  2316. SaveToEnv("NSS_ALLOW_LEGACY_DBM_ITERATION_COUNT=1");
  2317. #endif
  2318. #ifdef DEBUG
  2319. // Reduce the number of rounds for debug builds for perf/test reasons.
  2320. SaveToEnv("NSS_MAX_MP_PBE_ITERATION_COUNT=15");
  2321. #else
  2322. #ifdef MOZ_SECURITY_SQLSTORE
  2323. // We're using SQL; NSS's defaults for rounds are fine.
  2324. #else
  2325. // Set default Master Password rounds to a sane value for DBM which is slower
  2326. // than SQL for PBKDF. The NSS hard-coded default of 10,000 is too much.
  2327. // See also Bug 1606992 for perf issues.
  2328. SaveToEnv("NSS_MAX_MP_PBE_ITERATION_COUNT=500");
  2329. #endif
  2330. #endif
  2331. #ifdef CAIRO_HAS_DWRITE_FONT
  2332. {
  2333. // Bug 602792 - when DWriteCreateFactory is called the dwrite client dll
  2334. // starts the FntCache service if it isn't already running (it's set
  2335. // to manual startup by default in Windows 7 RTM). Subsequent DirectWrite
  2336. // calls cause the IDWriteFactory object to communicate with the FntCache
  2337. // service with a timeout; if there's no response after the timeout, the
  2338. // DirectWrite client library will assume the service isn't around and do
  2339. // manual font file I/O on _all_ system fonts. To avoid this, load the
  2340. // dwrite library and create a factory as early as possible so that the
  2341. // FntCache service is ready by the time it's needed.
  2342. CreateThread(nullptr, 0, &InitDwriteBG, nullptr, 0, nullptr);
  2343. }
  2344. #endif
  2345. #ifdef XP_UNIX
  2346. const char *home = PR_GetEnv("HOME");
  2347. if (!home || !*home) {
  2348. struct passwd *pw = getpwuid(geteuid());
  2349. if (!pw || !pw->pw_dir) {
  2350. Output(true, "Could not determine HOME directory");
  2351. return 1;
  2352. }
  2353. SaveWordToEnv("HOME", nsDependentCString(pw->pw_dir));
  2354. }
  2355. #endif
  2356. #ifdef MOZ_ACCESSIBILITY_ATK
  2357. // Suppress atk-bridge init at startup, until mozilla accessibility is
  2358. // initialized. This works after gnome 2.24.2.
  2359. SaveToEnv("NO_AT_BRIDGE=1");
  2360. #endif
  2361. // Check for application.ini overrides
  2362. const char* override = nullptr;
  2363. ar = CheckArg("override", true, &override);
  2364. if (ar == ARG_BAD) {
  2365. Output(true, "Incorrect number of arguments passed to --override");
  2366. return 1;
  2367. }
  2368. else if (ar == ARG_FOUND) {
  2369. nsCOMPtr<nsIFile> overrideLF;
  2370. rv = XRE_GetFileFromPath(override, getter_AddRefs(overrideLF));
  2371. if (NS_FAILED(rv)) {
  2372. Output(true, "Error: unrecognized override.ini path.\n");
  2373. return 1;
  2374. }
  2375. rv = XRE_ParseAppData(overrideLF, mAppData.get());
  2376. if (NS_FAILED(rv)) {
  2377. Output(true, "Couldn't read override.ini");
  2378. return 1;
  2379. }
  2380. }
  2381. // Check sanity and correctness of app data.
  2382. if (!mAppData->name) {
  2383. Output(true, "Error: App:Name not specified in application.ini\n");
  2384. return 1;
  2385. }
  2386. if (!mAppData->buildID) {
  2387. Output(true, "Error: App:BuildID not specified in application.ini\n");
  2388. return 1;
  2389. }
  2390. // XXX Originally ScopedLogging was here? Now it's in XRE_main above
  2391. // XRE_mainInit.
  2392. if (!mAppData->xreDirectory) {
  2393. nsCOMPtr<nsIFile> lf;
  2394. rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
  2395. if (NS_FAILED(rv))
  2396. return 2;
  2397. nsCOMPtr<nsIFile> greDir;
  2398. rv = lf->GetParent(getter_AddRefs(greDir));
  2399. if (NS_FAILED(rv))
  2400. return 2;
  2401. greDir.forget(&mAppData->xreDirectory);
  2402. }
  2403. if (!mAppData->directory) {
  2404. NS_IF_ADDREF(mAppData->directory = mAppData->xreDirectory);
  2405. }
  2406. if (mAppData->size > offsetof(nsXREAppData, minVersion)) {
  2407. if (!mAppData->minVersion) {
  2408. Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
  2409. return 1;
  2410. }
  2411. if (!mAppData->maxVersion) {
  2412. // If no maxVersion is specified, we assume the app is only compatible
  2413. // with the initial preview release. Do not increment this number ever!
  2414. SetAllocatedString(mAppData->maxVersion, "1.*");
  2415. }
  2416. if (mozilla::Version(mAppData->minVersion) > gToolkitVersion ||
  2417. mozilla::Version(mAppData->maxVersion) < gToolkitVersion) {
  2418. Output(true, "Error: Platform version '%s' is not compatible with\n"
  2419. "minVersion >= %s\nmaxVersion <= %s\n",
  2420. gToolkitVersion,
  2421. mAppData->minVersion, mAppData->maxVersion);
  2422. return 1;
  2423. }
  2424. }
  2425. rv = mDirProvider.Initialize(mAppData->directory, mAppData->xreDirectory);
  2426. if (NS_FAILED(rv))
  2427. return 1;
  2428. SaveToEnv("MOZ_LAUNCHED_CHILD=");
  2429. gRestartArgc = gArgc;
  2430. gRestartArgv = (char**) malloc(sizeof(char*) * (gArgc + 1 + (override ? 2 : 0)));
  2431. if (!gRestartArgv) {
  2432. return 1;
  2433. }
  2434. int i;
  2435. for (i = 0; i < gArgc; ++i) {
  2436. gRestartArgv[i] = gArgv[i];
  2437. }
  2438. // Add the -override argument back (it is removed automatically be CheckArg) if there is one
  2439. if (override) {
  2440. gRestartArgv[gRestartArgc++] = const_cast<char*>("-override");
  2441. gRestartArgv[gRestartArgc++] = const_cast<char*>(override);
  2442. }
  2443. gRestartArgv[gRestartArgc] = nullptr;
  2444. if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
  2445. gSafeMode = true;
  2446. // unset the env variable
  2447. SaveToEnv("MOZ_SAFE_MODE_RESTART=");
  2448. }
  2449. ar = CheckArg("safe-mode", true);
  2450. if (ar == ARG_BAD) {
  2451. PR_fprintf(PR_STDERR, "Error: argument --safe-mode is invalid when argument --osint is specified\n");
  2452. return 1;
  2453. } else if (ar == ARG_FOUND) {
  2454. gSafeMode = true;
  2455. }
  2456. #ifdef XP_WIN
  2457. // If the shift key is pressed and the ctrl and / or alt keys are not pressed
  2458. // during startup start in safe mode. GetKeyState returns a short and the high
  2459. // order bit will be 1 if the key is pressed. By masking the returned short
  2460. // with 0x8000 the result will be 0 if the key is not pressed and non-zero
  2461. // otherwise.
  2462. if ((GetKeyState(VK_SHIFT) & 0x8000) &&
  2463. !(GetKeyState(VK_CONTROL) & 0x8000) &&
  2464. !(GetKeyState(VK_MENU) & 0x8000) &&
  2465. !EnvHasValue("MOZ_DISABLE_SAFE_MODE_KEY")) {
  2466. gSafeMode = true;
  2467. }
  2468. #endif
  2469. #ifdef XP_WIN
  2470. {
  2471. // Add CPU microcode version to the crash report as "CPUMicrocodeVersion".
  2472. // It feels like this code may belong in nsSystemInfo instead.
  2473. int cpuUpdateRevision = -1;
  2474. HKEY key;
  2475. static const WCHAR keyName[] =
  2476. L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
  2477. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName , 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
  2478. DWORD updateRevision[2];
  2479. DWORD len = sizeof(updateRevision);
  2480. DWORD vtype;
  2481. // Windows 7 uses "Update Signature", 8 uses "Update Revision".
  2482. // For AMD CPUs, "CurrentPatchLevel" is sometimes used.
  2483. // Take the first one we find.
  2484. LPCWSTR choices[] = {L"Update Signature", L"Update Revision", L"CurrentPatchLevel"};
  2485. for (size_t oneChoice=0; oneChoice<ArrayLength(choices); oneChoice++) {
  2486. if (RegQueryValueExW(key, choices[oneChoice],
  2487. 0, &vtype,
  2488. reinterpret_cast<LPBYTE>(updateRevision),
  2489. &len) == ERROR_SUCCESS) {
  2490. if (vtype == REG_BINARY && len == sizeof(updateRevision)) {
  2491. // The first word is unused
  2492. cpuUpdateRevision = static_cast<int>(updateRevision[1]);
  2493. break;
  2494. } else if (vtype == REG_DWORD && len == sizeof(updateRevision[0])) {
  2495. cpuUpdateRevision = static_cast<int>(updateRevision[0]);
  2496. break;
  2497. }
  2498. }
  2499. }
  2500. }
  2501. }
  2502. #endif
  2503. // Handle --no-remote and --new-instance command line arguments. Setup
  2504. // the environment to better accommodate other components and various
  2505. // restart scenarios.
  2506. ar = CheckArg("no-remote", true);
  2507. if (ar == ARG_BAD) {
  2508. PR_fprintf(PR_STDERR, "Error: argument --no-remote is invalid when argument --osint is specified\n");
  2509. return 1;
  2510. } else if (ar == ARG_FOUND) {
  2511. SaveToEnv("MOZ_NO_REMOTE=1");
  2512. }
  2513. ar = CheckArg("new-instance", true);
  2514. if (ar == ARG_BAD) {
  2515. PR_fprintf(PR_STDERR, "Error: argument --new-instance is invalid when argument --osint is specified\n");
  2516. return 1;
  2517. } else if (ar == ARG_FOUND) {
  2518. SaveToEnv("MOZ_NEW_INSTANCE=1");
  2519. }
  2520. // Handle --help and --version command line arguments.
  2521. // They should return quickly, so we deal with them here.
  2522. if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
  2523. DumpHelp();
  2524. *aExitFlag = true;
  2525. return 0;
  2526. }
  2527. if (CheckArg("v") || CheckArg("version")) {
  2528. DumpVersion();
  2529. *aExitFlag = true;
  2530. return 0;
  2531. }
  2532. rv = XRE_InitCommandLine(gArgc, gArgv);
  2533. NS_ENSURE_SUCCESS(rv, 1);
  2534. // Check for --register, which registers chrome and then exits immediately.
  2535. ar = CheckArg("register", true);
  2536. if (ar == ARG_BAD) {
  2537. PR_fprintf(PR_STDERR, "Error: argument --register is invalid when argument --osint is specified\n");
  2538. return 1;
  2539. } else if (ar == ARG_FOUND) {
  2540. ScopedXPCOMStartup xpcom;
  2541. rv = xpcom.Initialize();
  2542. NS_ENSURE_SUCCESS(rv, 1);
  2543. {
  2544. nsCOMPtr<nsIChromeRegistry> chromeReg =
  2545. mozilla::services::GetChromeRegistryService();
  2546. NS_ENSURE_TRUE(chromeReg, 1);
  2547. chromeReg->CheckForNewChrome();
  2548. }
  2549. *aExitFlag = true;
  2550. return 0;
  2551. }
  2552. return 0;
  2553. }
  2554. namespace mozilla {
  2555. ShutdownChecksMode gShutdownChecks = SCM_NOTHING;
  2556. } // namespace mozilla
  2557. static void SetShutdownChecks() {
  2558. // Set default first. On debug builds we crash. On nightly and local
  2559. // builds we record. Nightlies will then send the info via telemetry,
  2560. // but it is usefull to have the data in about:telemetry in local builds
  2561. // too.
  2562. #ifdef DEBUG
  2563. gShutdownChecks = SCM_CRASH;
  2564. #else
  2565. const char* releaseChannel = NS_STRINGIFY(MOZ_UPDATE_CHANNEL);
  2566. if (strcmp(releaseChannel, "nightly") == 0 ||
  2567. strcmp(releaseChannel, "default") == 0) {
  2568. gShutdownChecks = SCM_RECORD;
  2569. } else {
  2570. gShutdownChecks = SCM_NOTHING;
  2571. }
  2572. #endif
  2573. // We let an environment variable override the default so that addons
  2574. // authors can use it for debugging shutdown with released firefox versions.
  2575. const char* mozShutdownChecksEnv = PR_GetEnv("MOZ_SHUTDOWN_CHECKS");
  2576. if (mozShutdownChecksEnv) {
  2577. if (strcmp(mozShutdownChecksEnv, "crash") == 0) {
  2578. gShutdownChecks = SCM_CRASH;
  2579. } else if (strcmp(mozShutdownChecksEnv, "record") == 0) {
  2580. gShutdownChecks = SCM_RECORD;
  2581. } else if (strcmp(mozShutdownChecksEnv, "nothing") == 0) {
  2582. gShutdownChecks = SCM_NOTHING;
  2583. }
  2584. }
  2585. }
  2586. /*
  2587. * XRE_mainStartup - Initializes the profile and various other services.
  2588. * Main() will exit early if either return value != 0 or if aExitFlag is
  2589. * true.
  2590. */
  2591. int
  2592. XREMain::XRE_mainStartup(bool* aExitFlag)
  2593. {
  2594. nsresult rv;
  2595. if (!aExitFlag)
  2596. return 1;
  2597. *aExitFlag = false;
  2598. SetShutdownChecks();
  2599. // Enable Telemetry IO Reporting on DEBUG, nightly and local builds
  2600. #ifdef DEBUG
  2601. mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
  2602. #else
  2603. {
  2604. const char* releaseChannel = NS_STRINGIFY(MOZ_UPDATE_CHANNEL);
  2605. if (strcmp(releaseChannel, "nightly") == 0 ||
  2606. strcmp(releaseChannel, "default") == 0) {
  2607. mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
  2608. }
  2609. }
  2610. #endif /* DEBUG */
  2611. #if defined(MOZ_WIDGET_GTK) || defined(MOZ_ENABLE_XREMOTE)
  2612. // Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear it.
  2613. #define HAVE_DESKTOP_STARTUP_ID
  2614. const char* desktopStartupIDEnv = PR_GetEnv("DESKTOP_STARTUP_ID");
  2615. if (desktopStartupIDEnv) {
  2616. mDesktopStartupID.Assign(desktopStartupIDEnv);
  2617. }
  2618. #endif
  2619. #if defined(MOZ_WIDGET_GTK)
  2620. // setup for private colormap. Ideally we'd like to do this
  2621. // in nsAppShell::Create, but we need to get in before gtk
  2622. // has been initialized to make sure everything is running
  2623. // consistently.
  2624. #if (MOZ_WIDGET_GTK == 2)
  2625. if (CheckArg("install"))
  2626. gdk_rgb_set_install(TRUE);
  2627. #endif
  2628. // Set program name to the one defined in application.ini.
  2629. {
  2630. nsAutoCString program(gAppData->name);
  2631. ToLowerCase(program);
  2632. g_set_prgname(program.get());
  2633. }
  2634. // Initialize GTK here for splash.
  2635. #if (MOZ_WIDGET_GTK == 3) && defined(MOZ_X11)
  2636. // Disable XInput2 support due to focus bugginess. See bugs 1182700, 1170342.
  2637. const char* useXI2 = PR_GetEnv("MOZ_USE_XINPUT2");
  2638. if (!useXI2 || (*useXI2 == '0'))
  2639. gdk_disable_multidevice();
  2640. #endif
  2641. // Open the display ourselves instead of using gtk_init, so that we can
  2642. // close it without fear that one day gtk might clean up the display it
  2643. // opens.
  2644. if (!gtk_parse_args(&gArgc, &gArgv))
  2645. return 1;
  2646. #endif /* MOZ_WIDGET_GTK */
  2647. #ifdef LIBFUZZER
  2648. if (PR_GetEnv("LIBFUZZER")) {
  2649. *aExitFlag = true;
  2650. return mozilla::libFuzzerRunner->Run();
  2651. }
  2652. #endif
  2653. if (PR_GetEnv("MOZ_RUN_GTEST")) {
  2654. int result;
  2655. #ifdef XP_WIN
  2656. UseParentConsole();
  2657. #endif
  2658. // RunGTest will only be set if we're in xul-unit
  2659. if (mozilla::RunGTest) {
  2660. gIsGtest = true;
  2661. result = mozilla::RunGTest();
  2662. gIsGtest = false;
  2663. } else {
  2664. result = 1;
  2665. printf("TEST-UNEXPECTED-FAIL | gtest | Not compiled with enable-tests\n");
  2666. }
  2667. *aExitFlag = true;
  2668. return result;
  2669. }
  2670. #if defined(MOZ_WIDGET_GTK)
  2671. // display_name is owned by gdk.
  2672. const char *display_name = gdk_get_display_arg_name();
  2673. bool saveDisplayArg = false;
  2674. if (display_name) {
  2675. saveDisplayArg = true;
  2676. } else {
  2677. display_name = detectDisplay();
  2678. if (!display_name) {
  2679. return 1;
  2680. }
  2681. }
  2682. #endif /* MOZ_WIDGET_GTK */
  2683. #ifdef MOZ_X11
  2684. // Init X11 in thread-safe mode. Must be called prior to the first call to XOpenDisplay
  2685. // (called inside gdk_display_open). This is a requirement for off main tread compositing.
  2686. XInitThreads();
  2687. #endif
  2688. #if defined(MOZ_WIDGET_GTK)
  2689. mGdkDisplay = gdk_display_open(display_name);
  2690. if (!mGdkDisplay) {
  2691. PR_fprintf(PR_STDERR, "Error: cannot open display: %s\n", display_name);
  2692. return 1;
  2693. }
  2694. gdk_display_manager_set_default_display (gdk_display_manager_get(),
  2695. mGdkDisplay);
  2696. if (GDK_IS_X11_DISPLAY(mGdkDisplay)) {
  2697. if (saveDisplayArg) {
  2698. SaveWordToEnv("DISPLAY", nsDependentCString(display_name));
  2699. }
  2700. } else {
  2701. mDisableRemote = true;
  2702. }
  2703. #endif
  2704. #ifdef MOZ_ENABLE_XREMOTE
  2705. // handle --remote now that xpcom is fired up
  2706. bool newInstance;
  2707. {
  2708. char *e = PR_GetEnv("MOZ_NO_REMOTE");
  2709. mDisableRemote = (mDisableRemote || (e && *e));
  2710. if (mDisableRemote) {
  2711. newInstance = true;
  2712. } else {
  2713. e = PR_GetEnv("MOZ_NEW_INSTANCE");
  2714. newInstance = (e && *e);
  2715. }
  2716. }
  2717. if (!newInstance) {
  2718. nsAutoCString program(gAppData->remotingName);
  2719. ToLowerCase(program);
  2720. const char* username = getenv("LOGNAME");
  2721. const char* profile = nullptr;
  2722. RemoteResult rr = ParseRemoteCommandLine(program, &profile, &username);
  2723. if (rr == REMOTE_ARG_BAD) {
  2724. return 1;
  2725. }
  2726. if (!username) {
  2727. struct passwd *pw = getpwuid(geteuid());
  2728. if (pw && pw->pw_name) {
  2729. // Beware that another call to getpwent/getpwname/getpwuid will overwrite
  2730. // pw, but we don't have such another call between here and when username
  2731. // is used last.
  2732. username = pw->pw_name;
  2733. }
  2734. }
  2735. nsCOMPtr<nsIFile> mutexDir;
  2736. rv = GetSpecialSystemDirectory(OS_TemporaryDirectory, getter_AddRefs(mutexDir));
  2737. if (NS_SUCCEEDED(rv)) {
  2738. nsAutoCString mutexPath = program + NS_LITERAL_CSTRING("_");
  2739. // In the unlikely even that LOGNAME is not set and getpwuid failed, just
  2740. // don't put the username in the mutex directory. It will conflict with
  2741. // other users mutex, but the worst that can happen is that they wait for
  2742. // MOZ_XREMOTE_START_TIMEOUT_SEC during startup in that case.
  2743. if (username) {
  2744. mutexPath.Append(username);
  2745. }
  2746. if (profile) {
  2747. mutexPath.Append(NS_LITERAL_CSTRING("_") + nsDependentCString(profile));
  2748. }
  2749. mutexDir->AppendNative(mutexPath);
  2750. rv = mutexDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
  2751. if (NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_ALREADY_EXISTS) {
  2752. mRemoteLockDir = mutexDir;
  2753. }
  2754. }
  2755. if (mRemoteLockDir) {
  2756. const TimeStamp epoch = mozilla::TimeStamp::Now();
  2757. do {
  2758. rv = mRemoteLock.Lock(mRemoteLockDir, nullptr);
  2759. if (NS_SUCCEEDED(rv))
  2760. break;
  2761. sched_yield();
  2762. } while ((TimeStamp::Now() - epoch)
  2763. < TimeDuration::FromSeconds(MOZ_XREMOTE_START_TIMEOUT_SEC));
  2764. if (NS_FAILED(rv)) {
  2765. NS_WARNING("Cannot lock XRemote start mutex");
  2766. }
  2767. }
  2768. // Try to remote the entire command line. If this fails, start up normally.
  2769. const char* desktopStartupIDPtr =
  2770. mDesktopStartupID.IsEmpty() ? nullptr : mDesktopStartupID.get();
  2771. rr = StartRemoteClient(desktopStartupIDPtr, program, profile, username);
  2772. if (rr == REMOTE_FOUND) {
  2773. *aExitFlag = true;
  2774. return 0;
  2775. } else if (rr == REMOTE_ARG_BAD) {
  2776. return 1;
  2777. }
  2778. }
  2779. #endif
  2780. #if defined(MOZ_WIDGET_GTK)
  2781. g_set_application_name(mAppData->name);
  2782. gtk_window_set_auto_startup_notification(false);
  2783. #if (MOZ_WIDGET_GTK == 2)
  2784. gtk_widget_set_default_colormap(gdk_rgb_get_colormap());
  2785. #endif /* (MOZ_WIDGET_GTK == 2) */
  2786. #endif /* defined(MOZ_WIDGET_GTK) */
  2787. #ifdef MOZ_X11
  2788. // Do this after initializing GDK, or GDK will install its own handler.
  2789. XRE_InstallX11ErrorHandler();
  2790. #endif
  2791. rv = NS_CreateNativeAppSupport(getter_AddRefs(mNativeApp));
  2792. if (NS_FAILED(rv))
  2793. return 1;
  2794. bool canRun = false;
  2795. rv = mNativeApp->Start(&canRun);
  2796. if (NS_FAILED(rv) || !canRun) {
  2797. return 1;
  2798. }
  2799. #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
  2800. // DESKTOP_STARTUP_ID is cleared now,
  2801. // we recover it in case we need a restart.
  2802. if (!mDesktopStartupID.IsEmpty()) {
  2803. nsAutoCString desktopStartupEnv;
  2804. desktopStartupEnv.AssignLiteral("DESKTOP_STARTUP_ID=");
  2805. desktopStartupEnv.Append(mDesktopStartupID);
  2806. // Leak it with extreme prejudice!
  2807. PR_SetEnv(ToNewCString(desktopStartupEnv));
  2808. }
  2809. #endif
  2810. #ifdef MOZ_UPDATER
  2811. // Check for and process any available updates
  2812. nsCOMPtr<nsIFile> updRoot;
  2813. bool persistent;
  2814. rv = mDirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
  2815. getter_AddRefs(updRoot));
  2816. // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
  2817. if (NS_FAILED(rv))
  2818. updRoot = mDirProvider.GetAppDir();
  2819. // If the MOZ_TEST_PROCESS_UPDATES environment variable already exists, then
  2820. // we are being called from the callback application.
  2821. if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
  2822. // If the caller has asked us to log our arguments, do so. This is used
  2823. // to make sure that the maintenance service successfully launches the
  2824. // callback application.
  2825. const char *logFile = nullptr;
  2826. if (ARG_FOUND == CheckArg("dump-args", false, &logFile)) {
  2827. FILE* logFP = fopen(logFile, "wb");
  2828. if (logFP) {
  2829. for (int i = 1; i < gRestartArgc; ++i) {
  2830. fprintf(logFP, "%s\n", gRestartArgv[i]);
  2831. }
  2832. fclose(logFP);
  2833. }
  2834. }
  2835. *aExitFlag = true;
  2836. return 0;
  2837. }
  2838. // Support for processing an update and exiting. The MOZ_TEST_PROCESS_UPDATES
  2839. // environment variable will be part of the updater's environment and the
  2840. // application that is relaunched by the updater. When the application is
  2841. // relaunched by the updater it will be removed below and the application
  2842. // will exit.
  2843. if (CheckArg("test-process-updates")) {
  2844. SaveToEnv("MOZ_TEST_PROCESS_UPDATES=1");
  2845. }
  2846. nsCOMPtr<nsIFile> exeFile, exeDir;
  2847. rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE, &persistent,
  2848. getter_AddRefs(exeFile));
  2849. NS_ENSURE_SUCCESS(rv, 1);
  2850. rv = exeFile->GetParent(getter_AddRefs(exeDir));
  2851. NS_ENSURE_SUCCESS(rv, 1);
  2852. ProcessUpdates(mDirProvider.GetGREDir(),
  2853. exeDir,
  2854. updRoot,
  2855. gRestartArgc,
  2856. gRestartArgv,
  2857. mAppData->version);
  2858. if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
  2859. SaveToEnv("MOZ_TEST_PROCESS_UPDATES=");
  2860. *aExitFlag = true;
  2861. return 0;
  2862. }
  2863. #endif
  2864. rv = NS_NewToolkitProfileService(getter_AddRefs(mProfileSvc));
  2865. if (rv == NS_ERROR_FILE_ACCESS_DENIED) {
  2866. PR_fprintf(PR_STDERR, "Error: Access was denied while trying to open files in " \
  2867. "your profile directory.\n");
  2868. }
  2869. if (NS_FAILED(rv)) {
  2870. // We failed to choose or create profile - notify user and quit
  2871. ProfileMissingDialog(mNativeApp);
  2872. return 1;
  2873. }
  2874. rv = SelectProfile(getter_AddRefs(mProfileLock), mProfileSvc, mNativeApp, &mStartOffline,
  2875. &mProfileName);
  2876. if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
  2877. rv == NS_ERROR_ABORT) {
  2878. *aExitFlag = true;
  2879. return 0;
  2880. }
  2881. if (NS_FAILED(rv)) {
  2882. // We failed to choose or create profile - notify user and quit
  2883. ProfileMissingDialog(mNativeApp);
  2884. return 1;
  2885. }
  2886. gProfileLock = mProfileLock;
  2887. rv = mProfileLock->GetDirectory(getter_AddRefs(mProfD));
  2888. NS_ENSURE_SUCCESS(rv, 1);
  2889. rv = mProfileLock->GetLocalDirectory(getter_AddRefs(mProfLD));
  2890. NS_ENSURE_SUCCESS(rv, 1);
  2891. rv = mDirProvider.SetProfile(mProfD, mProfLD);
  2892. NS_ENSURE_SUCCESS(rv, 1);
  2893. //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
  2894. mozilla::Telemetry::SetProfileDir(mProfD);
  2895. nsAutoCString version;
  2896. BuildVersion(version);
  2897. #ifdef TARGET_OS_ABI
  2898. NS_NAMED_LITERAL_CSTRING(osABI, TARGET_OS_ABI);
  2899. #else
  2900. // No TARGET_XPCOM_ABI, but at least the OS is known
  2901. NS_NAMED_LITERAL_CSTRING(osABI, OS_TARGET "_UNKNOWN");
  2902. #endif
  2903. // Check for version compatibility with the last version of the app this
  2904. // profile was started with. The format of the version stamp is defined
  2905. // by the BuildVersion function.
  2906. // Also check to see if something has happened to invalidate our
  2907. // fastload caches, like an extension upgrade or installation.
  2908. // If we see .purgecaches, that means someone did a make.
  2909. // Re-register components to catch potential changes.
  2910. nsCOMPtr<nsIFile> flagFile;
  2911. rv = NS_ERROR_FILE_NOT_FOUND;
  2912. nsCOMPtr<nsIFile> fFlagFile;
  2913. if (mAppData->directory) {
  2914. rv = mAppData->directory->Clone(getter_AddRefs(fFlagFile));
  2915. }
  2916. flagFile = do_QueryInterface(fFlagFile);
  2917. if (flagFile) {
  2918. flagFile->AppendNative(FILE_INVALIDATE_CACHES);
  2919. }
  2920. bool cachesOK;
  2921. bool versionOK = CheckCompatibility(mProfD, version, osABI,
  2922. mDirProvider.GetGREDir(),
  2923. mAppData->directory, flagFile,
  2924. &cachesOK);
  2925. if (CheckArg("purgecaches")) {
  2926. cachesOK = false;
  2927. }
  2928. if (PR_GetEnv("MOZ_PURGE_CACHES")) {
  2929. cachesOK = false;
  2930. }
  2931. // Every time a profile is loaded by a build with a different version,
  2932. // it updates the compatibility.ini file saying what version last wrote
  2933. // the fastload caches. On subsequent launches if the version matches,
  2934. // there is no need for re-registration. If the user loads the same
  2935. // profile in different builds the component registry must be
  2936. // re-generated to prevent mysterious component loading failures.
  2937. //
  2938. bool startupCacheValid = true;
  2939. if (gSafeMode) {
  2940. startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
  2941. WriteVersion(mProfD, NS_LITERAL_CSTRING("Safe Mode"), osABI,
  2942. mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
  2943. }
  2944. else if (versionOK) {
  2945. if (!cachesOK) {
  2946. // Remove caches, forcing component re-registration.
  2947. // The new list of additional components directories is derived from
  2948. // information in "extensions.ini".
  2949. startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
  2950. // Rewrite compatibility.ini to remove the flag
  2951. WriteVersion(mProfD, version, osABI,
  2952. mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
  2953. }
  2954. // Nothing need be done for the normal startup case.
  2955. }
  2956. else {
  2957. // Remove caches, forcing component re-registration
  2958. // with the default set of components (this disables any potentially
  2959. // troublesome incompatible XPCOM components).
  2960. startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, true);
  2961. // Write out version
  2962. WriteVersion(mProfD, version, osABI,
  2963. mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
  2964. }
  2965. if (!startupCacheValid)
  2966. StartupCache::IgnoreDiskCache();
  2967. if (flagFile) {
  2968. flagFile->Remove(true);
  2969. }
  2970. return 0;
  2971. }
  2972. /*
  2973. * XRE_mainRun - Command line startup, profile migration, and
  2974. * the calling of appStartup->Run().
  2975. */
  2976. nsresult
  2977. XREMain::XRE_mainRun()
  2978. {
  2979. nsresult rv = NS_OK;
  2980. NS_ASSERTION(mScopedXPCOM, "Scoped xpcom not initialized.");
  2981. #ifdef NS_FUNCTION_TIMER
  2982. // initialize some common services, so we don't pay the cost for these at odd times later on;
  2983. // SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs
  2984. {
  2985. nsCOMPtr<nsISupports> comp;
  2986. comp = do_GetService("@mozilla.org/preferences-service;1");
  2987. comp = do_GetService("@mozilla.org/network/socket-transport-service;1");
  2988. comp = do_GetService("@mozilla.org/network/dns-service;1");
  2989. comp = do_GetService("@mozilla.org/network/io-service;1");
  2990. comp = do_GetService("@mozilla.org/chrome/chrome-registry;1");
  2991. comp = do_GetService("@mozilla.org/focus-event-suppressor-service;1");
  2992. }
  2993. #endif
  2994. rv = mScopedXPCOM->SetWindowCreator(mNativeApp);
  2995. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  2996. if (mStartOffline) {
  2997. nsCOMPtr<nsIIOService2> io (do_GetService("@mozilla.org/network/io-service;1"));
  2998. NS_ENSURE_TRUE(io, NS_ERROR_FAILURE);
  2999. io->SetManageOfflineStatus(false);
  3000. io->SetOffline(true);
  3001. }
  3002. {
  3003. nsCOMPtr<nsIObserver> startupNotifier
  3004. (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
  3005. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  3006. startupNotifier->Observe(nullptr, APPSTARTUP_TOPIC, nullptr);
  3007. }
  3008. nsCOMPtr<nsIAppStartup> appStartup
  3009. (do_GetService(NS_APPSTARTUP_CONTRACTID));
  3010. NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
  3011. if (gDoMigration) {
  3012. nsCOMPtr<nsIFile> file;
  3013. mDirProvider.GetAppDir()->Clone(getter_AddRefs(file));
  3014. file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
  3015. nsINIParser parser;
  3016. nsresult rv = parser.Init(file);
  3017. // if override.ini doesn't exist, also check for distribution.ini
  3018. if (NS_FAILED(rv)) {
  3019. bool persistent;
  3020. mDirProvider.GetFile(XRE_APP_DISTRIBUTION_DIR, &persistent,
  3021. getter_AddRefs(file));
  3022. file->AppendNative(NS_LITERAL_CSTRING("distribution.ini"));
  3023. rv = parser.Init(file);
  3024. }
  3025. if (NS_SUCCEEDED(rv)) {
  3026. nsAutoCString buf;
  3027. rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
  3028. if (NS_SUCCEEDED(rv)) {
  3029. if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
  3030. gDoMigration = false;
  3031. }
  3032. }
  3033. }
  3034. }
  3035. {
  3036. nsCOMPtr<nsIToolkitProfile> profileBeingReset;
  3037. bool profileWasSelected = false;
  3038. if (gDoProfileReset) {
  3039. if (gResetOldProfileName.IsEmpty()) {
  3040. NS_WARNING("Not resetting profile as the profile has no name.");
  3041. gDoProfileReset = false;
  3042. } else {
  3043. rv = mProfileSvc->GetProfileByName(gResetOldProfileName,
  3044. getter_AddRefs(profileBeingReset));
  3045. if (NS_FAILED(rv)) {
  3046. gDoProfileReset = false;
  3047. return NS_ERROR_FAILURE;
  3048. }
  3049. nsCOMPtr<nsIToolkitProfile> defaultProfile;
  3050. // This can fail if there is no default profile.
  3051. // That shouldn't stop reset from proceeding.
  3052. nsresult gotSelected = mProfileSvc->GetSelectedProfile(getter_AddRefs(defaultProfile));
  3053. if (NS_SUCCEEDED(gotSelected)) {
  3054. profileWasSelected = defaultProfile == profileBeingReset;
  3055. }
  3056. }
  3057. }
  3058. // Profile Migration
  3059. if (mAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
  3060. gDoMigration = false;
  3061. nsCOMPtr<nsIProfileMigrator> pm(do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
  3062. if (pm) {
  3063. nsAutoCString aKey;
  3064. if (gDoProfileReset) {
  3065. // Automatically migrate from the current application if we just
  3066. // reset the profile.
  3067. // For Basilisk and Pale Moon:
  3068. // Hard-code MOZ_APP_NAME to firefox because of hard-coded type in migrator.
  3069. aKey = (((MOZ_APP_NAME == "basilisk")
  3070. || (MOZ_APP_NAME == "palemoon"))
  3071. ? "firefox" : MOZ_APP_NAME);
  3072. }
  3073. pm->Migrate(&mDirProvider, aKey, gResetOldProfileName);
  3074. }
  3075. }
  3076. if (gDoProfileReset) {
  3077. nsresult backupCreated = ProfileResetCleanup(profileBeingReset);
  3078. if (NS_FAILED(backupCreated)) NS_WARNING("Could not cleanup the profile that was reset");
  3079. nsCOMPtr<nsIToolkitProfile> newProfile;
  3080. rv = GetCurrentProfile(mProfileSvc, mProfD, getter_AddRefs(newProfile));
  3081. if (NS_SUCCEEDED(rv)) {
  3082. newProfile->SetName(gResetOldProfileName);
  3083. mProfileName.Assign(gResetOldProfileName);
  3084. // Set the new profile as the default after we're done cleaning up the old profile,
  3085. // iff that profile was already the default
  3086. if (profileWasSelected) {
  3087. rv = mProfileSvc->SetDefaultProfile(newProfile);
  3088. if (NS_FAILED(rv)) NS_WARNING("Could not set current profile as the default");
  3089. }
  3090. } else {
  3091. NS_WARNING("Could not find current profile to set as default / change name.");
  3092. }
  3093. // Need to write out the fact that the profile has been removed, the new profile
  3094. // renamed, and potentially that the selected/default profile changed.
  3095. mProfileSvc->Flush();
  3096. }
  3097. }
  3098. mDirProvider.DoStartup();
  3099. // As FilePreferences need the profile directory, we must initialize right here.
  3100. mozilla::FilePreferences::InitDirectoriesWhitelist();
  3101. mozilla::FilePreferences::InitPrefs();
  3102. OverrideDefaultLocaleIfNeeded();
  3103. appStartup->GetShuttingDown(&mShuttingDown);
  3104. nsCOMPtr<nsICommandLineRunner> cmdLine;
  3105. nsCOMPtr<nsIFile> workingDir;
  3106. rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
  3107. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  3108. if (!mShuttingDown) {
  3109. cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
  3110. NS_ENSURE_TRUE(cmdLine, NS_ERROR_FAILURE);
  3111. rv = cmdLine->Init(gArgc, gArgv, workingDir,
  3112. nsICommandLine::STATE_INITIAL_LAUNCH);
  3113. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  3114. /* Special-case services that need early access to the command
  3115. line. */
  3116. nsCOMPtr<nsIObserverService> obsService =
  3117. mozilla::services::GetObserverService();
  3118. if (obsService) {
  3119. obsService->NotifyObservers(cmdLine, "command-line-startup", nullptr);
  3120. }
  3121. }
  3122. #ifdef XP_WIN
  3123. // Hack to sync up the various environment storages. XUL_APP_FILE is special
  3124. // in that it comes from a different CRT (firefox.exe's static-linked copy).
  3125. // Ugly details in http://bugzil.la/1175039#c27
  3126. char appFile[MAX_PATH];
  3127. if (GetEnvironmentVariableA("XUL_APP_FILE", appFile, sizeof(appFile))) {
  3128. char* saved = PR_smprintf("XUL_APP_FILE=%s", appFile);
  3129. PR_SetEnv(saved);
  3130. PR_smprintf_free(saved);
  3131. }
  3132. #endif
  3133. SaveStateForAppInitiatedRestart();
  3134. // clear out any environment variables which may have been set
  3135. // during the relaunch process now that we know we won't be relaunching.
  3136. SaveToEnv("XRE_PROFILE_PATH=");
  3137. SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
  3138. SaveToEnv("XRE_PROFILE_NAME=");
  3139. SaveToEnv("XRE_START_OFFLINE=");
  3140. SaveToEnv("NO_EM_RESTART=");
  3141. SaveToEnv("XUL_APP_FILE=");
  3142. SaveToEnv("XRE_BINARY_PATH=");
  3143. if (!mShuttingDown) {
  3144. rv = appStartup->CreateHiddenWindow();
  3145. NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
  3146. #ifdef MOZ_STYLO
  3147. // We initialize Servo here so that the hidden DOM window is available,
  3148. // since initializing Servo calls style struct constructors, and the
  3149. // HackilyFindDeviceContext stuff we have right now depends on the hidden
  3150. // DOM window. When we fix that, this should move back to
  3151. // nsLayoutStatics.cpp
  3152. Servo_Initialize();
  3153. #endif
  3154. #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
  3155. nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
  3156. if (toolkit && !mDesktopStartupID.IsEmpty()) {
  3157. toolkit->SetDesktopStartupID(mDesktopStartupID);
  3158. }
  3159. // Clear the environment variable so it won't be inherited by
  3160. // child processes and confuse things.
  3161. g_unsetenv ("DESKTOP_STARTUP_ID");
  3162. #endif
  3163. nsCOMPtr<nsIObserverService> obsService =
  3164. mozilla::services::GetObserverService();
  3165. if (obsService)
  3166. obsService->NotifyObservers(nullptr, "final-ui-startup", nullptr);
  3167. (void)appStartup->DoneStartingUp();
  3168. appStartup->GetShuttingDown(&mShuttingDown);
  3169. }
  3170. if (!mShuttingDown) {
  3171. rv = cmdLine->Run();
  3172. NS_ENSURE_SUCCESS_LOG(rv, NS_ERROR_FAILURE);
  3173. appStartup->GetShuttingDown(&mShuttingDown);
  3174. }
  3175. if (!mShuttingDown) {
  3176. #ifdef MOZ_ENABLE_XREMOTE
  3177. // if we have X remote support, start listening for requests on the
  3178. // proxy window.
  3179. if (!mDisableRemote)
  3180. mRemoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
  3181. if (mRemoteService)
  3182. mRemoteService->Startup(mAppData->remotingName, mProfileName.get());
  3183. if (mRemoteLockDir) {
  3184. mRemoteLock.Unlock();
  3185. mRemoteLockDir->Remove(false);
  3186. }
  3187. #endif /* MOZ_ENABLE_XREMOTE */
  3188. mNativeApp->Enable();
  3189. }
  3190. #ifdef MOZ_INSTRUMENT_EVENT_LOOP
  3191. if (PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP")) {
  3192. bool logToConsole = true;
  3193. mozilla::InitEventTracing(logToConsole);
  3194. }
  3195. #endif /* MOZ_INSTRUMENT_EVENT_LOOP */
  3196. {
  3197. rv = appStartup->Run();
  3198. if (NS_FAILED(rv)) {
  3199. NS_ERROR("failed to run appstartup");
  3200. gLogConsoleErrors = true;
  3201. }
  3202. }
  3203. #ifdef MOZ_STYLO
  3204. // This, along with the call to Servo_Initialize, should eventually move back
  3205. // to nsLayoutStatics.cpp.
  3206. Servo_Shutdown();
  3207. #endif
  3208. return rv;
  3209. }
  3210. #if MOZ_WIDGET_GTK == 2
  3211. void XRE_GlibInit()
  3212. {
  3213. static bool ran_once = false;
  3214. // glib < 2.24 doesn't want g_thread_init to be invoked twice, so ensure
  3215. // we only do it once. No need for thread safety here, since this is invoked
  3216. // well before any thread is spawned.
  3217. if (!ran_once) {
  3218. // glib version < 2.36 doesn't initialize g_slice in a static initializer.
  3219. // Ensure this happens through g_thread_init (glib version < 2.32) or
  3220. // g_type_init (2.32 <= gLib version < 2.36)."
  3221. g_thread_init(nullptr);
  3222. g_type_init();
  3223. ran_once = true;
  3224. }
  3225. }
  3226. #endif
  3227. // Separate stub function to let us specifically suppress it in Valgrind
  3228. void
  3229. XRE_CreateStatsObject()
  3230. {
  3231. // Initialize global variables used by histogram collection
  3232. // machinery that is used by by Telemetry. Note: is never de-initialised.
  3233. Telemetry::CreateStatisticsRecorder();
  3234. }
  3235. /*
  3236. * XRE_main - A class based main entry point used by most platforms.
  3237. * Note that on OSX, aAppData->xreDirectory will point to
  3238. * .app/Contents/Resources.
  3239. */
  3240. int
  3241. XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
  3242. {
  3243. ScopedLogging log;
  3244. // NB: this must happen after the creation of |ScopedLogging log| since
  3245. // ScopedLogging::ScopedLogging calls NS_LogInit, and
  3246. // XRE_CreateStatsObject calls Telemetry::CreateStatisticsRecorder,
  3247. // and NS_LogInit must be called before Telemetry::CreateStatisticsRecorder.
  3248. // NS_LogInit must be called before Telemetry::CreateStatisticsRecorder
  3249. // so as to avoid many log messages of the form
  3250. // WARNING: XPCOM objects created/destroyed from static ctor/dtor: [..]
  3251. // See bug 1279614.
  3252. XRE_CreateStatsObject();
  3253. char aLocal;
  3254. GeckoProfilerInitRAII profilerGuard(&aLocal);
  3255. PROFILER_LABEL("Startup", "XRE_Main",
  3256. js::ProfileEntry::Category::OTHER);
  3257. nsresult rv = NS_OK;
  3258. gArgc = argc;
  3259. gArgv = argv;
  3260. NS_ENSURE_TRUE(aAppData, 2);
  3261. mAppData = new ScopedAppData(aAppData);
  3262. if (!mAppData)
  3263. return 1;
  3264. if (!mAppData->remotingName) {
  3265. SetAllocatedString(mAppData->remotingName, mAppData->name);
  3266. }
  3267. // used throughout this file
  3268. gAppData = mAppData;
  3269. nsCOMPtr<nsIFile> binFile;
  3270. rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(binFile));
  3271. NS_ENSURE_SUCCESS(rv, 1);
  3272. rv = binFile->GetPath(gAbsoluteArgv0Path);
  3273. NS_ENSURE_SUCCESS(rv, 1);
  3274. mozilla::IOInterposerInit ioInterposerGuard;
  3275. #if defined(XP_WIN)
  3276. // Some COM settings are global to the process and must be set before any non-
  3277. // trivial COM is run in the application. Since these settings may affect
  3278. // stability, we should instantiate COM ASAP so that we can ensure that these
  3279. // global settings are configured before anything can interfere.
  3280. mozilla::mscom::MainThreadRuntime msCOMRuntime;
  3281. #endif
  3282. #if MOZ_WIDGET_GTK == 2
  3283. XRE_GlibInit();
  3284. #endif
  3285. // init
  3286. bool exit = false;
  3287. int result = XRE_mainInit(&exit);
  3288. if (result != 0 || exit)
  3289. return result;
  3290. // startup
  3291. result = XRE_mainStartup(&exit);
  3292. if (result != 0 || exit)
  3293. return result;
  3294. bool appInitiatedRestart = false;
  3295. // Start the real application
  3296. mScopedXPCOM = MakeUnique<ScopedXPCOMStartup>();
  3297. if (!mScopedXPCOM)
  3298. return 1;
  3299. rv = mScopedXPCOM->Initialize();
  3300. NS_ENSURE_SUCCESS(rv, 1);
  3301. // run!
  3302. rv = XRE_mainRun();
  3303. #ifdef MOZ_INSTRUMENT_EVENT_LOOP
  3304. mozilla::ShutdownEventTracing();
  3305. #endif
  3306. gAbsoluteArgv0Path.Truncate();
  3307. // Check for an application initiated restart. This is one that
  3308. // corresponds to nsIAppStartup.quit(eRestart)
  3309. if (rv == NS_SUCCESS_RESTART_APP
  3310. || rv == NS_SUCCESS_RESTART_APP_NOT_SAME_PROFILE) {
  3311. appInitiatedRestart = true;
  3312. // We have an application restart don't do any shutdown checks here
  3313. // In particular we don't want to poison IO for checking late-writes.
  3314. gShutdownChecks = SCM_NOTHING;
  3315. }
  3316. if (!mShuttingDown) {
  3317. #ifdef MOZ_ENABLE_XREMOTE
  3318. // shut down the x remote proxy window
  3319. if (mRemoteService) {
  3320. mRemoteService->Shutdown();
  3321. }
  3322. #endif /* MOZ_ENABLE_XREMOTE */
  3323. }
  3324. mScopedXPCOM = nullptr;
  3325. #if defined(XP_WIN)
  3326. mozilla::widget::StopAudioSession();
  3327. #endif
  3328. // unlock the profile after ScopedXPCOMStartup object (xpcom)
  3329. // has gone out of scope. see bug #386739 for more details
  3330. mProfileLock->Unlock();
  3331. gProfileLock = nullptr;
  3332. // Restart the app after XPCOM has been shut down cleanly.
  3333. if (appInitiatedRestart) {
  3334. RestoreStateForAppInitiatedRestart();
  3335. if (rv != NS_SUCCESS_RESTART_APP_NOT_SAME_PROFILE) {
  3336. // Ensure that these environment variables are set:
  3337. SaveFileToEnvIfUnset("XRE_PROFILE_PATH", mProfD);
  3338. SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", mProfLD);
  3339. SaveWordToEnvIfUnset("XRE_PROFILE_NAME", mProfileName);
  3340. }
  3341. #ifdef MOZ_WIDGET_GTK
  3342. MOZ_gdk_display_close(mGdkDisplay);
  3343. #endif
  3344. {
  3345. rv = LaunchChild(mNativeApp, true);
  3346. }
  3347. return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
  3348. }
  3349. #ifdef MOZ_WIDGET_GTK
  3350. // gdk_display_close also calls gdk_display_manager_set_default_display
  3351. // appropriately when necessary.
  3352. MOZ_gdk_display_close(mGdkDisplay);
  3353. #endif
  3354. XRE_DeinitCommandLine();
  3355. return NS_FAILED(rv) ? 1 : 0;
  3356. }
  3357. void
  3358. XRE_StopLateWriteChecks(void) {
  3359. mozilla::StopLateWriteChecks();
  3360. }
  3361. int
  3362. XRE_main(int argc, char* argv[], const nsXREAppData* aAppData, uint32_t aFlags)
  3363. {
  3364. XREMain main;
  3365. int result = main.XRE_main(argc, argv, aAppData);
  3366. mozilla::RecordShutdownEndTimeStamp();
  3367. return result;
  3368. }
  3369. nsresult
  3370. XRE_InitCommandLine(int aArgc, char* aArgv[])
  3371. {
  3372. nsresult rv = NS_OK;
  3373. #if defined(OS_WIN)
  3374. CommandLine::Init(aArgc, aArgv);
  3375. #else
  3376. // these leak on error, but that's OK: we'll just exit()
  3377. char** canonArgs = new char*[aArgc];
  3378. // get the canonical version of the binary's path
  3379. nsCOMPtr<nsIFile> binFile;
  3380. rv = XRE_GetBinaryPath(aArgv[0], getter_AddRefs(binFile));
  3381. if (NS_FAILED(rv))
  3382. return NS_ERROR_FAILURE;
  3383. nsAutoCString canonBinPath;
  3384. rv = binFile->GetNativePath(canonBinPath);
  3385. if (NS_FAILED(rv))
  3386. return NS_ERROR_FAILURE;
  3387. canonArgs[0] = strdup(canonBinPath.get());
  3388. for (int i = 1; i < aArgc; ++i) {
  3389. if (aArgv[i]) {
  3390. canonArgs[i] = strdup(aArgv[i]);
  3391. }
  3392. }
  3393. NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!");
  3394. CommandLine::Init(aArgc, canonArgs);
  3395. for (int i = 0; i < aArgc; ++i)
  3396. free(canonArgs[i]);
  3397. delete[] canonArgs;
  3398. #endif
  3399. if (PR_GetEnv("UXP_CUSTOM_OMNI")) {
  3400. // Process CLI parameters for specifying custom omnijars
  3401. const char *path = nullptr;
  3402. ArgResult ar = CheckArg("greomni", true, &path);
  3403. if (ar == ARG_BAD) {
  3404. PR_fprintf(PR_STDERR,
  3405. "Error: argument --greomni requires a path argument or the "
  3406. "--osint argument was specified with the --greomni argument "
  3407. "which is invalid.\n");
  3408. return NS_ERROR_FAILURE;
  3409. }
  3410. if (!path)
  3411. return rv;
  3412. nsCOMPtr<nsIFile> greOmni;
  3413. rv = XRE_GetFileFromPath(path, getter_AddRefs(greOmni));
  3414. if (NS_FAILED(rv)) {
  3415. PR_fprintf(PR_STDERR, "Error: argument --greomni requires a valid path\n");
  3416. return rv;
  3417. }
  3418. ar = CheckArg("appomni", true, &path);
  3419. if (ar == ARG_BAD) {
  3420. PR_fprintf(PR_STDERR,
  3421. "Error: argument --appomni requires a path argument or the "
  3422. "--osint argument was specified with the --appomni argument "
  3423. "which is invalid.\n");
  3424. return NS_ERROR_FAILURE;
  3425. }
  3426. nsCOMPtr<nsIFile> appOmni;
  3427. if (path) {
  3428. rv = XRE_GetFileFromPath(path, getter_AddRefs(appOmni));
  3429. if (NS_FAILED(rv)) {
  3430. PR_fprintf(PR_STDERR, "Error: argument --appomni requires a valid path\n");
  3431. return rv;
  3432. }
  3433. }
  3434. mozilla::Omnijar::Init(greOmni, appOmni);
  3435. } // UXP_CUSTOM_OMNI
  3436. return rv;
  3437. }
  3438. nsresult
  3439. XRE_DeinitCommandLine()
  3440. {
  3441. nsresult rv = NS_OK;
  3442. CommandLine::Terminate();
  3443. return rv;
  3444. }
  3445. GeckoProcessType
  3446. XRE_GetProcessType()
  3447. {
  3448. return mozilla::startup::sChildProcessType;
  3449. }
  3450. bool
  3451. XRE_IsGPUProcess()
  3452. {
  3453. return XRE_GetProcessType() == GeckoProcessType_GPU;
  3454. }
  3455. bool
  3456. XRE_IsParentProcess()
  3457. {
  3458. return XRE_GetProcessType() == GeckoProcessType_Default;
  3459. }
  3460. bool
  3461. XRE_IsContentProcess()
  3462. {
  3463. return XRE_GetProcessType() == GeckoProcessType_Content;
  3464. }
  3465. // If you add anything to this enum, please update about:support to reflect it
  3466. enum {
  3467. kE10sEnabledByUser = 0,
  3468. kE10sEnabledByDefault = 1,
  3469. kE10sDisabledByUser = 2,
  3470. // kE10sDisabledInSafeMode = 3, was removed in bug 1172491.
  3471. kE10sDisabledForAccessibility = 4,
  3472. // kE10sDisabledForMacGfx = 5, was removed in bug 1068674.
  3473. // kE10sDisabledForBidi = 6, removed in bug 1309599
  3474. kE10sDisabledForAddons = 7,
  3475. kE10sForceDisabled = 8,
  3476. // kE10sDisabledForXPAcceleration = 9, removed in bug 1296353
  3477. // kE10sDisabledForOperatingSystem = 10, removed due to xp-eol
  3478. };
  3479. const char* kAccessibilityLastRunDatePref = "accessibility.lastLoadDate";
  3480. const char* kAccessibilityLoadedLastSessionPref = "accessibility.loadedInLastSession";
  3481. #if defined(XP_WIN)
  3482. static inline uint32_t
  3483. PRTimeToSeconds(PRTime t_usec)
  3484. {
  3485. PRTime usec_per_sec = PR_USEC_PER_SEC;
  3486. return uint32_t(t_usec /= usec_per_sec);
  3487. }
  3488. #endif
  3489. uint32_t
  3490. MultiprocessBlockPolicy() {
  3491. if (gMultiprocessBlockPolicyInitialized) {
  3492. return gMultiprocessBlockPolicy;
  3493. }
  3494. gMultiprocessBlockPolicyInitialized = true;
  3495. // We do not support E10S, block by policy.
  3496. gMultiprocessBlockPolicy = kE10sForceDisabled;
  3497. return gMultiprocessBlockPolicy;
  3498. }
  3499. bool
  3500. mozilla::BrowserTabsRemoteAutostart()
  3501. {
  3502. if (gBrowserTabsRemoteAutostartInitialized) {
  3503. return gBrowserTabsRemoteAutostart;
  3504. }
  3505. gBrowserTabsRemoteAutostartInitialized = true;
  3506. bool optInPref = Preferences::GetBool("browser.tabs.remote.autostart", false);
  3507. bool trialPref = Preferences::GetBool("browser.tabs.remote.autostart.2", false);
  3508. bool prefEnabled = optInPref || trialPref;
  3509. int status;
  3510. if (prefEnabled) {
  3511. uint32_t blockPolicy = MultiprocessBlockPolicy();
  3512. if (blockPolicy != 0) {
  3513. status = blockPolicy;
  3514. } else {
  3515. MOZ_CRASH("e10s force enabled bypassing policy -- unsupported configuration");
  3516. }
  3517. } else {
  3518. status = kE10sDisabledByUser;
  3519. }
  3520. gBrowserTabsRemoteStatus = status;
  3521. return gBrowserTabsRemoteAutostart;
  3522. }
  3523. void
  3524. SetupErrorHandling(const char* progname)
  3525. {
  3526. #ifdef XP_WIN
  3527. /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
  3528. we still want DEP protection: enable it explicitly and programmatically.
  3529. This function is not available on WinXPSP2 so we dynamically load it.
  3530. */
  3531. HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
  3532. SetProcessDEPPolicyFunc _SetProcessDEPPolicy =
  3533. (SetProcessDEPPolicyFunc) GetProcAddress(kernel32, "SetProcessDEPPolicy");
  3534. if (_SetProcessDEPPolicy)
  3535. _SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
  3536. #endif
  3537. #ifdef XP_WIN32
  3538. // Suppress the "DLL Foo could not be found" dialog, such that if dependent
  3539. // libraries (such as GDI+) are not preset, we gracefully fail to load those
  3540. // XPCOM components, instead of being ungraceful.
  3541. UINT realMode = SetErrorMode(0);
  3542. realMode |= SEM_FAILCRITICALERRORS;
  3543. // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
  3544. // application has crashed" dialog box. This is mainly useful for
  3545. // automated testing environments, e.g. tinderbox, where there's no need
  3546. // for a dozen of the dialog boxes to litter the console
  3547. if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
  3548. realMode |= SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
  3549. SetErrorMode(realMode);
  3550. #endif
  3551. #if defined (DEBUG) && defined(XP_WIN)
  3552. // Send MSCRT Warnings, Errors and Assertions to stderr.
  3553. // See http://msdn.microsoft.com/en-us/library/1y71x448(v=VS.80).aspx
  3554. // and http://msdn.microsoft.com/en-us/library/a68f826y(v=VS.80).aspx.
  3555. _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
  3556. _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
  3557. _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
  3558. _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
  3559. _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
  3560. _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
  3561. _CrtSetReportHook(MSCRTReportHook);
  3562. #endif
  3563. InstallSignalHandlers(progname);
  3564. // Unbuffer stdout, needed for tinderbox tests.
  3565. setbuf(stdout, 0);
  3566. }
  3567. void
  3568. OverrideDefaultLocaleIfNeeded() {
  3569. // Read pref to decide whether to override default locale with US English.
  3570. if (mozilla::Preferences::GetBool("javascript.use_us_english_locale", false)) {
  3571. // Set the application-wide C-locale. Needed to resist fingerprinting
  3572. // of Date.toLocaleFormat(). We use the locale to "C.UTF-8" if possible,
  3573. // to avoid interfering with non-ASCII keyboard input on some Linux desktops.
  3574. // Otherwise fall back to the "C" locale, which is available on all platforms.
  3575. setlocale(LC_ALL, "C.UTF-8") || setlocale(LC_ALL, "C");
  3576. }
  3577. }
  3578. void
  3579. XRE_EnableSameExecutableForContentProc() {
  3580. if (!PR_GetEnv("MOZ_SEPARATE_CHILD_PROCESS")) {
  3581. mozilla::ipc::GeckoChildProcessHost::EnableSameExecutableForContentProc();
  3582. }
  3583. }