123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "mozilla/dom/ContentParent.h"
- #include "mozilla/dom/ContentChild.h"
- #include "mozilla/ipc/GeckoChildProcessHost.h"
- #include "mozilla/ArrayUtils.h"
- #include "mozilla/Attributes.h"
- #include "mozilla/FilePreferences.h"
- #include "mozilla/ChaosMode.h"
- #include "mozilla/IOInterposer.h"
- #include "mozilla/Likely.h"
- #include "mozilla/MemoryChecking.h"
- #include "mozilla/Poison.h"
- #include "mozilla/Preferences.h"
- #include "mozilla/ScopeExit.h"
- #include "mozilla/Services.h"
- #include "mozilla/ServoBindings.h"
- #include "mozilla/Telemetry.h"
- #include "nsAppRunner.h"
- #include "mozilla/AppData.h"
- #ifdef MOZ_UPDATER
- #include "nsUpdateDriver.h"
- #endif
- #include "ProfileReset.h"
- #ifdef MOZ_INSTRUMENT_EVENT_LOOP
- #include "EventTracer.h"
- #endif
- #include "prmem.h"
- #include "prnetdb.h"
- #include "prprf.h"
- #include "prproces.h"
- #include "prenv.h"
- #include "prtime.h"
- #include "nsIAppShellService.h"
- #include "nsIAppStartup.h"
- #include "nsIAppStartupNotifier.h"
- #include "nsIMutableArray.h"
- #include "nsICategoryManager.h"
- #include "nsIChromeRegistry.h"
- #include "nsICommandLineRunner.h"
- #include "nsIComponentManager.h"
- #include "nsIComponentRegistrar.h"
- #include "nsIConsoleService.h"
- #include "nsIContentHandler.h"
- #include "nsIDialogParamBlock.h"
- #include "nsIDOMWindow.h"
- #include "mozilla/ModuleUtils.h"
- #include "nsIIOService2.h"
- #include "nsIObserverService.h"
- #include "nsINativeAppSupport.h"
- #include "nsIPlatformInfo.h"
- #include "nsIProcess.h"
- #include "nsIProfileUnlocker.h"
- #include "nsIPromptService.h"
- #include "nsIServiceManager.h"
- #include "nsIStringBundle.h"
- #include "nsISupportsPrimitives.h"
- #include "nsIToolkitChromeRegistry.h"
- #include "nsIToolkitProfile.h"
- #include "nsIToolkitProfileService.h"
- #include "nsIURI.h"
- #include "nsIURL.h"
- #include "nsIWindowCreator.h"
- #include "nsIWindowMediator.h"
- #include "nsIWindowWatcher.h"
- #include "nsIXULAppInfo.h"
- #include "nsIXULRuntime.h"
- #include "nsPIDOMWindow.h"
- #include "nsIBaseWindow.h"
- #include "nsIWidget.h"
- #include "nsIDocShell.h"
- #include "nsAppShellCID.h"
- #include "mozilla/scache/StartupCache.h"
- #include "gfxPrefs.h"
- #include "mozilla/Unused.h"
- #ifdef XP_WIN
- #include "nsIWinAppHelper.h"
- #include <windows.h>
- #include <intrin.h>
- #include <math.h>
- #include "cairo/cairo-features.h"
- #include "mozilla/mscom/MainThreadRuntime.h"
- #include "mozilla/widget/AudioSession.h"
- #ifndef PROCESS_DEP_ENABLE
- #define PROCESS_DEP_ENABLE 0x1
- #endif
- #endif
- #ifdef ACCESSIBILITY
- #include "nsAccessibilityService.h"
- #if defined(XP_WIN)
- #include "mozilla/a11y/Compatibility.h"
- #endif
- #endif
- #include "nsCRT.h"
- #include "nsCOMPtr.h"
- #include "nsDirectoryServiceDefs.h"
- #include "nsDirectoryServiceUtils.h"
- #include "nsEmbedCID.h"
- #include "nsNetUtil.h"
- #include "nsReadableUtils.h"
- #include "nsXPCOM.h"
- #include "nsXPCOMCIDInternal.h"
- #include "nsXPIDLString.h"
- #include "nsPrintfCString.h"
- #include "nsVersionComparator.h"
- #include "nsAppDirectoryServiceDefs.h"
- #include "nsXULAppAPI.h"
- #include "nsXREDirProvider.h"
- #include "nsToolkitCompsCID.h"
- #include "nsINIParser.h"
- #include "mozilla/Omnijar.h"
- #include "mozilla/StartupTimeline.h"
- #include "mozilla/LateWriteChecks.h"
- #include <stdlib.h>
- #include <locale.h>
- #ifdef XP_UNIX
- #include <sys/stat.h>
- #include <unistd.h>
- #include <pwd.h>
- #endif
- #ifdef XP_WIN
- #include <process.h>
- #include <shlobj.h>
- #include "nsThreadUtils.h"
- #include <comdef.h>
- #include <wbemidl.h>
- #include "WinUtils.h"
- #endif
- // for X remote support
- #ifdef MOZ_ENABLE_XREMOTE
- #include "XRemoteClient.h"
- #include "nsIRemoteService.h"
- #include "nsProfileLock.h"
- #include "SpecialSystemDirectory.h"
- #include <sched.h>
- // Time to wait for the remoting service to start
- #define MOZ_XREMOTE_START_TIMEOUT_SEC 5
- #endif
- #if defined(DEBUG) && defined(XP_WIN32)
- #include <malloc.h>
- #endif
- #ifdef DEBUG
- #include "mozilla/Logging.h"
- #endif
- #include "base/command_line.h"
- #include "GTestRunner.h"
- extern uint32_t gRestartMode;
- extern void InstallSignalHandlers(const char *ProgramName);
- #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
- #define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")
- int gArgc;
- char **gArgv;
- static const char gToolkitVersion[] = NS_STRINGIFY(GRE_MILESTONE);
- static const char gToolkitBuildID[] = NS_STRINGIFY(MOZ_BUILDID);
- static nsIProfileLock* gProfileLock;
- int gRestartArgc;
- char **gRestartArgv;
- bool gIsGtest = false;
- nsString gAbsoluteArgv0Path;
- #if defined(MOZ_WIDGET_GTK)
- #include <glib.h>
- #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING)
- #define CLEANUP_MEMORY 1
- #define PANGO_ENABLE_BACKEND
- #include <pango/pangofc-fontmap.h>
- #endif
- #include <gtk/gtk.h>
- #ifdef MOZ_X11
- #include <gdk/gdkx.h>
- #endif /* MOZ_X11 */
- #include "nsGTKToolkit.h"
- #include <fontconfig/fontconfig.h>
- #endif
- #include "BinaryPath.h"
- #ifndef MOZ_BUILDID
- // See comment in Makefile.in why we want to avoid including buildid.h.
- // Still include it when MOZ_BUILDID is not set, which can happen with some
- // build backends.
- #include "buildid.h"
- #endif
- #ifdef MOZ_LINKER
- extern "C" MFBT_API bool IsSignalHandlingBroken();
- #endif
- #ifdef LIBFUZZER
- #include "LibFuzzerRunner.h"
- namespace mozilla {
- LibFuzzerRunner* libFuzzerRunner = 0;
- } // namespace mozilla
- extern "C" MOZ_EXPORT void XRE_LibFuzzerSetMain(int argc, char** argv, LibFuzzerMain main) {
- mozilla::libFuzzerRunner->setParams(argc, argv, main);
- }
- #endif
- namespace mozilla {
- int (*RunGTest)() = 0;
- } // namespace mozilla
- using namespace mozilla;
- using mozilla::Unused;
- using mozilla::scache::StartupCache;
- using mozilla::dom::ContentParent;
- using mozilla::dom::ContentChild;
- // Save literal putenv string to environment variable.
- static void
- SaveToEnv(const char *putenv)
- {
- char *expr = strdup(putenv);
- if (expr)
- PR_SetEnv(expr);
- // We intentionally leak |expr| here since it is required by PR_SetEnv.
- MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(expr);
- }
- // Tests that an environment variable exists and has a value
- static bool
- EnvHasValue(const char *name)
- {
- const char *val = PR_GetEnv(name);
- return (val && *val);
- }
- // Save the given word to the specified environment variable.
- static void
- SaveWordToEnv(const char *name, const nsACString & word)
- {
- char *expr = PR_smprintf("%s=%s", name, PromiseFlatCString(word).get());
- if (expr)
- PR_SetEnv(expr);
- // We intentionally leak |expr| here since it is required by PR_SetEnv.
- }
- // Save the path of the given file to the specified environment variable.
- static void
- SaveFileToEnv(const char *name, nsIFile *file)
- {
- #ifdef XP_WIN
- nsAutoString path;
- file->GetPath(path);
- SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
- #else
- nsAutoCString path;
- file->GetNativePath(path);
- SaveWordToEnv(name, path);
- #endif
- }
- // Load the path of a file saved with SaveFileToEnv
- static already_AddRefed<nsIFile>
- GetFileFromEnv(const char *name)
- {
- nsresult rv;
- nsCOMPtr<nsIFile> file;
- #ifdef XP_WIN
- WCHAR path[_MAX_PATH];
- if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(),
- path, _MAX_PATH))
- return nullptr;
- rv = NS_NewLocalFile(nsDependentString(path), true, getter_AddRefs(file));
- if (NS_FAILED(rv))
- return nullptr;
- return file.forget();
- #else
- const char *arg = PR_GetEnv(name);
- if (!arg || !*arg)
- return nullptr;
- rv = NS_NewNativeLocalFile(nsDependentCString(arg), true,
- getter_AddRefs(file));
- if (NS_FAILED(rv))
- return nullptr;
- return file.forget();
- #endif
- }
- // Save the path of the given word to the specified environment variable
- // provided the environment variable does not have a value.
- static void
- SaveWordToEnvIfUnset(const char *name, const nsACString & word)
- {
- if (!EnvHasValue(name))
- SaveWordToEnv(name, word);
- }
- // Save the path of the given file to the specified environment variable
- // provided the environment variable does not have a value.
- static void
- SaveFileToEnvIfUnset(const char *name, nsIFile *file)
- {
- if (!EnvHasValue(name))
- SaveFileToEnv(name, file);
- }
- static bool
- strimatch(const char* lowerstr, const char* mixedstr)
- {
- while(*lowerstr) {
- if (!*mixedstr) return false; // mixedstr is shorter
- if (tolower(*mixedstr) != *lowerstr) return false; // no match
- ++lowerstr;
- ++mixedstr;
- }
- if (*mixedstr) return false; // lowerstr is shorter
- return true;
- }
- static bool gIsExpectedExit = false;
- void MozExpectedExit() {
- gIsExpectedExit = true;
- }
- /**
- * Runs atexit() to catch unexpected exit from 3rd party libraries like the
- * Intel graphics driver calling exit in an error condition. When they
- * call exit() to report an error we won't shutdown correctly and wont catch
- * the issue with our crash reporter.
- */
- static void UnexpectedExit() {
- if (!gIsExpectedExit) {
- gIsExpectedExit = true; // Don't risk re-entrency issues when crashing.
- MOZ_CRASH("Exit called by third party code.");
- }
- }
- /**
- * Output a string to the user. This method is really only meant to be used to
- * output last-ditch error messages designed for developers NOT END USERS.
- *
- * @param isError
- * Pass true to indicate severe errors.
- * @param fmt
- * printf-style format string followed by arguments.
- */
- static void Output(bool isError, const char *fmt, ... )
- {
- va_list ap;
- va_start(ap, fmt);
- #if defined(XP_WIN) && !MOZ_WINCONSOLE
- char *msg = PR_vsmprintf(fmt, ap);
- if (msg)
- {
- UINT flags = MB_OK;
- if (isError)
- flags |= MB_ICONERROR;
- else
- flags |= MB_ICONINFORMATION;
- wchar_t wide_msg[1024];
- MultiByteToWideChar(CP_ACP,
- 0,
- msg,
- -1,
- wide_msg,
- sizeof(wide_msg) / sizeof(wchar_t));
- MessageBoxW(nullptr, wide_msg, L"XULRunner", flags);
- PR_smprintf_free(msg);
- }
- #else
- vfprintf(stderr, fmt, ap);
- #endif
- va_end(ap);
- }
- enum RemoteResult {
- REMOTE_NOT_FOUND = 0,
- REMOTE_FOUND = 1,
- REMOTE_ARG_BAD = 2
- };
- enum ArgResult {
- ARG_NONE = 0,
- ARG_FOUND = 1,
- ARG_BAD = 2 // you wanted a param, but there isn't one
- };
- static void RemoveArg(char **argv)
- {
- do {
- *argv = *(argv + 1);
- ++argv;
- } while (*argv);
- --gArgc;
- }
- /**
- * Check for a commandline flag. If the flag takes a parameter, the
- * parameter is returned in aParam. Flags may be in the form -arg or
- * --arg (or /arg on win32).
- *
- * @param aArg the parameter to check. Must be lowercase.
- * @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
- * when aArg is also present.
- * @param aParam if non-null, the -arg <data> will be stored in this pointer.
- * This is *not* allocated, but rather a pointer to the argv data.
- * @param aRemArg if true, the argument is removed from the gArgv array.
- */
- static ArgResult
- CheckArg(const char* aArg, bool aCheckOSInt = false, const char **aParam = nullptr, bool aRemArg = true)
- {
- MOZ_ASSERT(gArgv, "gArgv must be initialized before CheckArg()");
- char **curarg = gArgv + 1; // skip argv[0]
- ArgResult ar = ARG_NONE;
- while (*curarg) {
- char *arg = curarg[0];
- if (arg[0] == '-'
- #if defined(XP_WIN)
- || *arg == '/'
- #endif
- ) {
- ++arg;
- if (*arg == '-')
- ++arg;
- if (strimatch(aArg, arg)) {
- if (aRemArg)
- RemoveArg(curarg);
- else
- ++curarg;
- if (!aParam) {
- ar = ARG_FOUND;
- break;
- }
- if (*curarg) {
- if (**curarg == '-'
- #if defined(XP_WIN)
- || **curarg == '/'
- #endif
- )
- return ARG_BAD;
- *aParam = *curarg;
- if (aRemArg)
- RemoveArg(curarg);
- ar = ARG_FOUND;
- break;
- }
- return ARG_BAD;
- }
- }
- ++curarg;
- }
- if (aCheckOSInt && ar == ARG_FOUND) {
- ArgResult arOSInt = CheckArg("osint");
- if (arOSInt == ARG_FOUND) {
- ar = ARG_BAD;
- PR_fprintf(PR_STDERR, "Error: argument --osint is invalid\n");
- }
- }
- return ar;
- }
- #if defined(XP_WIN)
- /**
- * Check for a commandline flag from the windows shell and remove it from the
- * argv used when restarting. Flags MUST be in the form -arg.
- *
- * @param aArg the parameter to check. Must be lowercase.
- */
- static ArgResult
- CheckArgShell(const char* aArg)
- {
- char **curarg = gRestartArgv + 1; // skip argv[0]
- while (*curarg) {
- char *arg = curarg[0];
- if (arg[0] == '-') {
- ++arg;
- if (strimatch(aArg, arg)) {
- do {
- *curarg = *(curarg + 1);
- ++curarg;
- } while (*curarg);
- --gRestartArgc;
- return ARG_FOUND;
- }
- }
- ++curarg;
- }
- return ARG_NONE;
- }
- /**
- * Enabled Native App Support to process DDE messages when the app needs to
- * restart and the app has been launched by the Windows shell to open an url.
- * When aWait is false this will process the DDE events manually. This prevents
- * Windows from displaying an error message due to the DDE message not being
- * acknowledged.
- */
- static void
- ProcessDDE(nsINativeAppSupport* aNative, bool aWait)
- {
- // When the app is launched by the windows shell the windows shell
- // expects the app to be available for DDE messages and if it isn't
- // windows displays an error dialog. To prevent the error the DDE server
- // is enabled and pending events are processed when the app needs to
- // restart after it was launched by the shell with the requestpending
- // argument. The requestpending pending argument is removed to
- // differentiate it from being launched when an app restart is not
- // required.
- ArgResult ar;
- ar = CheckArgShell("requestpending");
- if (ar == ARG_FOUND) {
- aNative->Enable(); // enable win32 DDE responses
- if (aWait) {
- nsIThread *thread = NS_GetCurrentThread();
- // This is just a guesstimate based on testing different values.
- // If count is 8 or less windows will display an error dialog.
- int32_t count = 20;
- while(--count >= 0) {
- NS_ProcessNextEvent(thread);
- PR_Sleep(PR_MillisecondsToInterval(1));
- }
- }
- }
- }
- #endif
- /**
- * Determines if there is support for showing the profile manager
- *
- * @return true in all environments
- */
- static bool
- CanShowProfileManager()
- {
- return true;
- }
- bool gSafeMode = false;
- /**
- * The nsXULAppInfo object implements nsIFactory so that it can be its own
- * singleton.
- */
- class nsXULAppInfo : public nsIXULAppInfo,
- public nsIObserver,
- #ifdef XP_WIN
- public nsIWinAppHelper,
- #endif
- public nsIXULRuntime
- {
- public:
- constexpr nsXULAppInfo() {}
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSIPLATFORMINFO
- NS_DECL_NSIXULAPPINFO
- NS_DECL_NSIXULRUNTIME
- NS_DECL_NSIOBSERVER
- #ifdef XP_WIN
- NS_DECL_NSIWINAPPHELPER
- #endif
- };
- NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
- NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
- NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
- NS_INTERFACE_MAP_ENTRY(nsIObserver)
- #ifdef XP_WIN
- NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
- #endif
- NS_INTERFACE_MAP_ENTRY(nsIPlatformInfo)
- NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData ||
- XRE_IsContentProcess())
- NS_INTERFACE_MAP_END
- NS_IMETHODIMP_(MozExternalRefCountType)
- nsXULAppInfo::AddRef()
- {
- return 1;
- }
- NS_IMETHODIMP_(MozExternalRefCountType)
- nsXULAppInfo::Release()
- {
- return 1;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetVendor(nsACString& aResult)
- {
- if (XRE_IsContentProcess()) {
- ContentChild* cc = ContentChild::GetSingleton();
- aResult = cc->GetAppInfo().vendor;
- return NS_OK;
- }
- aResult.Assign(gAppData->vendor);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetName(nsACString& aResult)
- {
- if (XRE_IsContentProcess()) {
- ContentChild* cc = ContentChild::GetSingleton();
- aResult = cc->GetAppInfo().name;
- return NS_OK;
- }
- aResult.Assign(gAppData->name);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetID(nsACString& aResult)
- {
- if (XRE_IsContentProcess()) {
- ContentChild* cc = ContentChild::GetSingleton();
- aResult = cc->GetAppInfo().ID;
- return NS_OK;
- }
- aResult.Assign(gAppData->ID);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetVersion(nsACString& aResult)
- {
- if (XRE_IsContentProcess()) {
- ContentChild* cc = ContentChild::GetSingleton();
- aResult = cc->GetAppInfo().version;
- return NS_OK;
- }
- aResult.Assign(gAppData->version);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetPlatformVersion(nsACString& aResult)
- {
- aResult.Assign(gToolkitVersion);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetAppBuildID(nsACString& aResult)
- {
- if (XRE_IsContentProcess()) {
- ContentChild* cc = ContentChild::GetSingleton();
- aResult = cc->GetAppInfo().buildID;
- return NS_OK;
- }
- aResult.Assign(gAppData->buildID);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetPlatformBuildID(nsACString& aResult)
- {
- aResult.Assign(gToolkitBuildID);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetUAName(nsACString& aResult)
- {
- if (XRE_IsContentProcess()) {
- ContentChild* cc = ContentChild::GetSingleton();
- aResult = cc->GetAppInfo().UAName;
- return NS_OK;
- }
- aResult.Assign(gAppData->UAName);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetLogConsoleErrors(bool *aResult)
- {
- *aResult = gLogConsoleErrors;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::SetLogConsoleErrors(bool aValue)
- {
- gLogConsoleErrors = aValue;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetInSafeMode(bool *aResult)
- {
- *aResult = gSafeMode;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetOS(nsACString& aResult)
- {
- aResult.AssignLiteral(OS_TARGET);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetXPCOMABI(nsACString& aResult)
- {
- #ifdef TARGET_XPCOM_ABI
- aResult.AssignLiteral(TARGET_XPCOM_ABI);
- return NS_OK;
- #else
- return NS_ERROR_NOT_AVAILABLE;
- #endif
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetWidgetToolkit(nsACString& aResult)
- {
- aResult.AssignLiteral(MOZ_WIDGET_TOOLKIT);
- return NS_OK;
- }
- // Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,
- // is synchronized with the const unsigned longs defined in
- // xpcom/system/nsIXULRuntime.idl.
- #define SYNC_ENUMS(a,b) \
- static_assert(nsIXULRuntime::PROCESS_TYPE_ ## a == \
- static_cast<int>(GeckoProcessType_ ## b), \
- "GeckoProcessType in nsXULAppAPI.h not synchronized with nsIXULRuntime.idl");
- SYNC_ENUMS(DEFAULT, Default)
- SYNC_ENUMS(PLUGIN, Plugin)
- SYNC_ENUMS(CONTENT, Content)
- SYNC_ENUMS(IPDLUNITTEST, IPDLUnitTest)
- SYNC_ENUMS(GMPLUGIN, GMPlugin)
- SYNC_ENUMS(GPU, GPU)
- // .. and ensure that that is all of them:
- static_assert(GeckoProcessType_GPU + 1 == GeckoProcessType_End,
- "Did not find the final GeckoProcessType");
- NS_IMETHODIMP
- nsXULAppInfo::GetProcessType(uint32_t* aResult)
- {
- NS_ENSURE_ARG_POINTER(aResult);
- *aResult = XRE_GetProcessType();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetProcessID(uint32_t* aResult)
- {
- #ifdef XP_WIN
- *aResult = GetCurrentProcessId();
- #else
- *aResult = getpid();
- #endif
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetUniqueProcessID(uint64_t* aResult)
- {
- if (XRE_IsContentProcess()) {
- ContentChild* cc = ContentChild::GetSingleton();
- *aResult = cc->GetID();
- } else {
- *aResult = 0;
- }
- return NS_OK;
- }
- static bool gBrowserTabsRemoteAutostart = false;
- static uint64_t gBrowserTabsRemoteStatus = 0;
- static bool gBrowserTabsRemoteAutostartInitialized = false;
- static bool gMultiprocessBlockPolicyInitialized = false;
- static uint32_t gMultiprocessBlockPolicy = 0;
- NS_IMETHODIMP
- nsXULAppInfo::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData) {
- if (!nsCRT::strcmp(aTopic, "getE10SBlocked")) {
- nsCOMPtr<nsISupportsPRUint64> ret = do_QueryInterface(aSubject);
- if (!ret)
- return NS_ERROR_FAILURE;
- ret->SetData(gBrowserTabsRemoteStatus);
- return NS_OK;
- }
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetBrowserTabsRemoteAutostart(bool* aResult)
- {
- *aResult = BrowserTabsRemoteAutostart();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetMultiprocessBlockPolicy(uint32_t* aResult)
- {
- *aResult = MultiprocessBlockPolicy();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetAccessibilityEnabled(bool* aResult)
- {
- #ifdef ACCESSIBILITY
- *aResult = GetAccService() != nullptr;
- #else
- *aResult = false;
- #endif
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetIs64Bit(bool* aResult)
- {
- #ifdef HAVE_64BIT_BUILD
- *aResult = true;
- #else
- *aResult = false;
- #endif
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::EnsureContentProcess()
- {
- if (!XRE_IsParentProcess())
- return NS_ERROR_NOT_AVAILABLE;
- RefPtr<ContentParent> unused = ContentParent::GetNewOrUsedBrowserProcess();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::InvalidateCachesOnRestart()
- {
- nsCOMPtr<nsIFile> file;
- nsresult rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP,
- getter_AddRefs(file));
- if (NS_FAILED(rv))
- return rv;
- if (!file)
- return NS_ERROR_NOT_AVAILABLE;
- file->AppendNative(FILE_COMPATIBILITY_INFO);
- nsINIParser parser;
- rv = parser.Init(file);
- if (NS_FAILED(rv)) {
- // This fails if compatibility.ini is not there, so we'll
- // flush the caches on the next restart anyways.
- return NS_OK;
- }
- nsAutoCString buf;
- rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
- if (NS_FAILED(rv)) {
- PRFileDesc *fd;
- rv = file->OpenNSPRFileDesc(PR_RDWR | PR_APPEND, 0600, &fd);
- if (NS_FAILED(rv)) {
- NS_ERROR("could not create output stream");
- return NS_ERROR_NOT_AVAILABLE;
- }
- static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1" NS_LINEBREAK;
- PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
- PR_Close(fd);
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetReplacedLockTime(PRTime *aReplacedLockTime)
- {
- if (!gProfileLock)
- return NS_ERROR_NOT_AVAILABLE;
- gProfileLock->GetReplacedLockTime(aReplacedLockTime);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetLastRunCrashID(nsAString &aLastRunCrashID)
- {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetIsReleaseOrBeta(bool* aResult)
- {
- #ifdef RELEASE_OR_BETA
- *aResult = true;
- #else
- *aResult = false;
- #endif
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetIsOfficialBranding(bool* aResult)
- {
- #ifdef MOZ_OFFICIAL_BRANDING
- *aResult = true;
- #else
- *aResult = false;
- #endif
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetDefaultUpdateChannel(nsACString& aResult)
- {
- aResult.AssignLiteral(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetDistributionID(nsACString& aResult)
- {
- aResult.AssignLiteral(MOZ_DISTRIBUTION_ID);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetIsOfficial(bool* aResult)
- {
- #ifdef MC_OFFICIAL
- *aResult = true;
- #else
- *aResult = false;
- #endif
- return NS_OK;
- }
- NS_IMETHODIMP
- nsXULAppInfo::GetWindowsDLLBlocklistStatus(bool* aResult)
- {
- #if defined(XP_WIN)
- *aResult = gAppData->flags & NS_XRE_DLL_BLOCKLIST_ENABLED;
- #else
- *aResult = false;
- #endif
- return NS_OK;
- }
- #ifdef XP_WIN
- // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
- // safely build with the Vista SDK and without it.
- typedef enum
- {
- VistaTokenElevationTypeDefault = 1,
- VistaTokenElevationTypeFull,
- VistaTokenElevationTypeLimited
- } VISTA_TOKEN_ELEVATION_TYPE;
- // avoid collision with TokeElevationType enum in WinNT.h
- // of the Vista SDK
- #define VistaTokenElevationType static_cast< TOKEN_INFORMATION_CLASS >( 18 )
- NS_IMETHODIMP
- nsXULAppInfo::GetUserCanElevate(bool *aUserCanElevate)
- {
- HANDLE hToken;
- VISTA_TOKEN_ELEVATION_TYPE elevationType;
- DWORD dwSize;
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) ||
- !GetTokenInformation(hToken, VistaTokenElevationType, &elevationType,
- sizeof(elevationType), &dwSize)) {
- *aUserCanElevate = false;
- }
- else {
- // The possible values returned for elevationType and their meanings are:
- // TokenElevationTypeDefault: The token does not have a linked token
- // (e.g. UAC disabled or a standard user, so they can't be elevated)
- // TokenElevationTypeFull: The token is linked to an elevated token
- // (e.g. UAC is enabled and the user is already elevated so they can't
- // be elevated again)
- // TokenElevationTypeLimited: The token is linked to a limited token
- // (e.g. UAC is enabled and the user is not elevated, so they can be
- // elevated)
- *aUserCanElevate = (elevationType == VistaTokenElevationTypeLimited);
- }
- if (hToken)
- CloseHandle(hToken);
- return NS_OK;
- }
- #endif
- static const nsXULAppInfo kAppInfo;
- static nsresult AppInfoConstructor(nsISupports* aOuter,
- REFNSIID aIID, void **aResult)
- {
- NS_ENSURE_NO_AGGREGATION(aOuter);
- return const_cast<nsXULAppInfo*>(&kAppInfo)->
- QueryInterface(aIID, aResult);
- }
- bool gLogConsoleErrors = false;
- #define NS_ENSURE_TRUE_LOG(x, ret) \
- PR_BEGIN_MACRO \
- if (MOZ_UNLIKELY(!(x))) { \
- NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
- gLogConsoleErrors = true; \
- return ret; \
- } \
- PR_END_MACRO
- #define NS_ENSURE_SUCCESS_LOG(res, ret) \
- NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)
- /**
- * Because we're starting/stopping XPCOM several times in different scenarios,
- * this class is a stack-based critter that makes sure that XPCOM is shut down
- * during early returns.
- */
- class ScopedXPCOMStartup
- {
- public:
- ScopedXPCOMStartup() :
- mServiceManager(nullptr) { }
- ~ScopedXPCOMStartup();
- nsresult Initialize();
- nsresult SetWindowCreator(nsINativeAppSupport* native);
- static nsresult CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult);
- private:
- nsIServiceManager* mServiceManager;
- static nsINativeAppSupport* gNativeAppSupport;
- };
- ScopedXPCOMStartup::~ScopedXPCOMStartup()
- {
- NS_IF_RELEASE(gNativeAppSupport);
- if (mServiceManager) {
- nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
- if (appStartup)
- appStartup->DestroyHiddenWindow();
- gDirServiceProvider->DoShutdown();
- PROFILER_MARKER("Shutdown early");
- WriteConsoleLog();
- NS_ShutdownXPCOM(mServiceManager);
- mServiceManager = nullptr;
- }
- }
- // {95d89e3e-a169-41a3-8e56-719978e15b12}
- #define APPINFO_CID \
- { 0x95d89e3e, 0xa169, 0x41a3, { 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 } }
- // {0C4A446C-EE82-41f2-8D04-D366D2C7A7D4}
- static const nsCID kNativeAppSupportCID =
- { 0xc4a446c, 0xee82, 0x41f2, { 0x8d, 0x4, 0xd3, 0x66, 0xd2, 0xc7, 0xa7, 0xd4 } };
- // {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}
- static const nsCID kProfileServiceCID =
- { 0x5f5e59ce, 0x27bc, 0x47eb, { 0x9d, 0x1f, 0xb0, 0x9c, 0xa9, 0x4, 0x98, 0x36 } };
- static already_AddRefed<nsIFactory>
- ProfileServiceFactoryConstructor(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry)
- {
- nsCOMPtr<nsIFactory> factory;
- NS_NewToolkitProfileFactory(getter_AddRefs(factory));
- return factory.forget();
- }
- NS_DEFINE_NAMED_CID(APPINFO_CID);
- static const mozilla::Module::CIDEntry kXRECIDs[] = {
- { &kAPPINFO_CID, false, nullptr, AppInfoConstructor },
- { &kProfileServiceCID, false, ProfileServiceFactoryConstructor, nullptr },
- { &kNativeAppSupportCID, false, nullptr, ScopedXPCOMStartup::CreateAppSupport },
- { nullptr }
- };
- static const mozilla::Module::ContractIDEntry kXREContracts[] = {
- { XULAPPINFO_SERVICE_CONTRACTID, &kAPPINFO_CID },
- { XULRUNTIME_SERVICE_CONTRACTID, &kAPPINFO_CID },
- { NS_PROFILESERVICE_CONTRACTID, &kProfileServiceCID },
- { NS_NATIVEAPPSUPPORT_CONTRACTID, &kNativeAppSupportCID },
- { nullptr }
- };
- static const mozilla::Module kXREModule = {
- mozilla::Module::kVersion,
- kXRECIDs,
- kXREContracts
- };
- NSMODULE_DEFN(Apprunner) = &kXREModule;
- nsresult
- ScopedXPCOMStartup::Initialize()
- {
- NS_ASSERTION(gDirServiceProvider, "Should not get here!");
- nsresult rv;
- rv = NS_InitXPCOM2(&mServiceManager, gDirServiceProvider->GetAppDir(),
- gDirServiceProvider);
- if (NS_FAILED(rv)) {
- NS_ERROR("Couldn't start xpcom!");
- mServiceManager = nullptr;
- }
- else {
- #ifdef DEBUG
- nsCOMPtr<nsIComponentRegistrar> reg =
- do_QueryInterface(mServiceManager);
- NS_ASSERTION(reg, "Service Manager doesn't QI to Registrar.");
- #endif
- }
- return rv;
- }
- /**
- * This is a little factory class that serves as a singleton-service-factory
- * for the nativeappsupport object.
- */
- class nsSingletonFactory final : public nsIFactory
- {
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIFACTORY
- explicit nsSingletonFactory(nsISupports* aSingleton);
- private:
- ~nsSingletonFactory() { }
- nsCOMPtr<nsISupports> mSingleton;
- };
- nsSingletonFactory::nsSingletonFactory(nsISupports* aSingleton)
- : mSingleton(aSingleton)
- {
- NS_ASSERTION(mSingleton, "Singleton was null!");
- }
- NS_IMPL_ISUPPORTS(nsSingletonFactory, nsIFactory)
- NS_IMETHODIMP
- nsSingletonFactory::CreateInstance(nsISupports* aOuter,
- const nsIID& aIID,
- void* *aResult)
- {
- NS_ENSURE_NO_AGGREGATION(aOuter);
- return mSingleton->QueryInterface(aIID, aResult);
- }
- NS_IMETHODIMP
- nsSingletonFactory::LockFactory(bool)
- {
- return NS_OK;
- }
- /**
- * Set our windowcreator on the WindowWatcher service.
- */
- nsresult
- ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport* native)
- {
- nsresult rv;
- NS_IF_ADDREF(gNativeAppSupport = native);
- // Inform the chrome registry about OS accessibility
- nsCOMPtr<nsIToolkitChromeRegistry> cr =
- mozilla::services::GetToolkitChromeRegistryService();
- if (cr)
- cr->CheckForOSAccessibility();
- nsCOMPtr<nsIWindowCreator> creator (do_GetService(NS_APPSTARTUP_CONTRACTID));
- if (!creator) return NS_ERROR_UNEXPECTED;
- nsCOMPtr<nsIWindowWatcher> wwatch
- (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
- NS_ENSURE_SUCCESS(rv, rv);
- return wwatch->SetWindowCreator(creator);
- }
- /* static */ nsresult
- ScopedXPCOMStartup::CreateAppSupport(nsISupports* aOuter, REFNSIID aIID, void** aResult)
- {
- if (aOuter)
- return NS_ERROR_NO_AGGREGATION;
- if (!gNativeAppSupport)
- return NS_ERROR_NOT_INITIALIZED;
- return gNativeAppSupport->QueryInterface(aIID, aResult);
- }
- nsINativeAppSupport* ScopedXPCOMStartup::gNativeAppSupport;
- static void DumpArbitraryHelp()
- {
- nsresult rv;
- ScopedLogging log;
- {
- ScopedXPCOMStartup xpcom;
- xpcom.Initialize();
- nsCOMPtr<nsICommandLineRunner> cmdline
- (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
- if (!cmdline)
- return;
- nsCString text;
- rv = cmdline->GetHelpText(text);
- if (NS_SUCCEEDED(rv))
- printf("%s", text.get());
- }
- }
- // English text needs to go into a dtd file.
- // But when this is called we have no components etc. These strings must either be
- // here, or in a native resource file.
- static void
- DumpHelp()
- {
- printf("Usage: %s [ options ... ] [URL]\n"
- " where options include:\n\n", gArgv[0]);
- #ifdef MOZ_X11
- printf("X11 options\n"
- " --display=DISPLAY X display to use.\n"
- " --sync Make X calls synchronous.\n");
- #endif
- #ifdef XP_UNIX
- printf(" --g-fatal-warnings Make all warnings fatal.\n"
- "\n%s options\n", gAppData->name);
- #endif
- printf(" -h or --help Print this message.\n"
- " -v or --version Print %s version.\n"
- " -P <profile> Start with <profile>.\n"
- " --profile <path> Start with profile at <path>.\n"
- #ifdef MC_BASILISK
- " --migration Start with migration wizard.\n"
- #endif
- " --ProfileManager Start with ProfileManager.\n"
- " --no-remote Do not accept or send remote commands;\n"
- " implies --new-instance.\n"
- " --new-instance Open new instance, not a new window\n"
- " in running instance.\n"
- " --UILocale <locale> Start with <locale> resources as UI Locale.\n"
- " --safe-mode Disables extensions and themes for this session.\n", (const char*) gAppData->name);
- #if defined(XP_WIN)
- printf(" --console Start %s with a debugging console.\n", (const char*) gAppData->name);
- #endif
- // this works, but only after the components have registered. so if you drop in a new command line handler, --help
- // won't not until the second run.
- // out of the bug, because we ship a component.reg file, it works correctly.
- DumpArbitraryHelp();
- }
- #if defined(DEBUG) && defined(XP_WIN)
- #ifdef DEBUG_warren
- #define _CRTDBG_MAP_ALLOC
- #endif
- // Set a CRT ReportHook function to capture and format MSCRT
- // warnings, errors and assertions.
- // See http://msdn.microsoft.com/en-US/library/74kabxyx(v=VS.80).aspx
- #include <stdio.h>
- #include <crtdbg.h>
- #include "mozilla/mozalloc_abort.h"
- static int MSCRTReportHook( int aReportType, char *aMessage, int *oReturnValue)
- {
- *oReturnValue = 0; // continue execution
- // Do not use fprintf or other functions which may allocate
- // memory from the heap which may be corrupted. Instead,
- // use fputs to output the leading portion of the message
- // and use mozalloc_abort to emit the remainder of the
- // message.
- switch(aReportType) {
- case 0:
- fputs("\nWARNING: CRT WARNING", stderr);
- fputs(aMessage, stderr);
- fputs("\n", stderr);
- break;
- case 1:
- fputs("\n###!!! ABORT: CRT ERROR ", stderr);
- mozalloc_abort(aMessage);
- break;
- case 2:
- fputs("\n###!!! ABORT: CRT ASSERT ", stderr);
- mozalloc_abort(aMessage);
- break;
- }
- // do not invoke the debugger
- return 1;
- }
- #endif
- static inline void
- DumpVersion()
- {
- if (gAppData->vendor)
- printf("%s ", gAppData->vendor);
- printf("%s %s", gAppData->name, gAppData->version);
- if (gAppData->copyright)
- printf(", %s", gAppData->copyright);
- printf("\n");
- }
- #ifdef MOZ_ENABLE_XREMOTE
- static RemoteResult
- ParseRemoteCommandLine(nsCString& program,
- const char** profile,
- const char** username)
- {
- ArgResult ar;
- ar = CheckArg("p", false, profile, false);
- if (ar == ARG_BAD) {
- // Leave it to the normal command line handling to handle this situation.
- return REMOTE_NOT_FOUND;
- }
- const char *temp = nullptr;
- ar = CheckArg("a", true, &temp);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
- return REMOTE_ARG_BAD;
- } else if (ar == ARG_FOUND) {
- program.Assign(temp);
- }
- ar = CheckArg("u", true, username);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
- return REMOTE_ARG_BAD;
- }
- return REMOTE_FOUND;
- }
- static RemoteResult
- StartRemoteClient(const char* aDesktopStartupID,
- nsCString& program,
- const char* profile,
- const char* username)
- {
- XRemoteClient client;
- nsresult rv = client.Init();
- if (NS_FAILED(rv))
- return REMOTE_NOT_FOUND;
- nsXPIDLCString response;
- bool success = false;
- rv = client.SendCommandLine(program.get(), username, profile,
- gArgc, gArgv, aDesktopStartupID,
- getter_Copies(response), &success);
- // did the command fail?
- if (!success)
- return REMOTE_NOT_FOUND;
- // The "command not parseable" error is returned when the
- // nsICommandLineHandler throws a NS_ERROR_ABORT.
- if (response.EqualsLiteral("500 command not parseable"))
- return REMOTE_ARG_BAD;
- if (NS_FAILED(rv))
- return REMOTE_NOT_FOUND;
- return REMOTE_FOUND;
- }
- #endif // MOZ_ENABLE_XREMOTE
- void
- XRE_InitOmnijar(nsIFile* greOmni, nsIFile* appOmni)
- {
- mozilla::Omnijar::Init(greOmni, appOmni);
- }
- nsresult
- XRE_GetBinaryPath(const char* argv0, nsIFile* *aResult)
- {
- return mozilla::BinaryPath::GetFile(argv0, aResult);
- }
- #ifdef XP_WIN
- #include "nsWindowsRestart.cpp"
- #include <shellapi.h>
- typedef BOOL (WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
- #endif
- // If aBlankCommandLine is true, then the application will be launched with a
- // blank command line instead of being launched with the same command line that
- // it was initially started with.
- static nsresult LaunchChild(nsINativeAppSupport* aNative,
- bool aBlankCommandLine = false)
- {
- aNative->Quit(); // release DDE mutex, if we're holding it
- // Restart this process by exec'ing it into the current process
- // if supported by the platform. Otherwise, use NSPR.
- if (aBlankCommandLine) {
- gRestartArgc = 1;
- gRestartArgv[gRestartArgc] = nullptr;
- }
- SaveToEnv("MOZ_LAUNCHED_CHILD=1");
- nsCOMPtr<nsIFile> lf;
- nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
- if (NS_FAILED(rv))
- return rv;
- #if defined(XP_WIN)
- nsAutoString exePath;
- rv = lf->GetPath(exePath);
- if (NS_FAILED(rv))
- return rv;
- if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv))
- return NS_ERROR_FAILURE;
- #else
- nsAutoCString exePath;
- rv = lf->GetNativePath(exePath);
- if (NS_FAILED(rv))
- return rv;
- #if defined(XP_UNIX)
- if (execv(exePath.get(), gRestartArgv) == -1)
- return NS_ERROR_FAILURE;
- #else
- PRProcess* process = PR_CreateProcess(exePath.get(), gRestartArgv,
- nullptr, nullptr);
- if (!process) return NS_ERROR_FAILURE;
- int32_t exitCode;
- PRStatus failed = PR_WaitProcess(process, &exitCode);
- if (failed || exitCode)
- return NS_ERROR_FAILURE;
- #endif // XP_UNIX
- #endif // WP_WIN
- return NS_ERROR_LAUNCHED_CHILD_PROCESS;
- }
- static const char kProfileProperties[] =
- "chrome://mozapps/locale/profile/profileSelection.properties";
- namespace {
- /**
- * This class, instead of a raw nsresult, should be the return type of any
- * function called by SelectProfile that initializes XPCOM.
- */
- class ReturnAbortOnError
- {
- public:
- MOZ_IMPLICIT ReturnAbortOnError(nsresult aRv)
- {
- mRv = ConvertRv(aRv);
- }
- operator nsresult()
- {
- return mRv;
- }
- private:
- inline nsresult
- ConvertRv(nsresult aRv)
- {
- if (NS_SUCCEEDED(aRv) || aRv == NS_ERROR_LAUNCHED_CHILD_PROCESS) {
- return aRv;
- }
- return NS_ERROR_ABORT;
- }
- nsresult mRv;
- };
- } // namespace
- static ReturnAbortOnError
- ProfileLockedDialog(nsIFile* aProfileDir, nsIFile* aProfileLocalDir,
- nsIProfileUnlocker* aUnlocker,
- nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
- {
- nsresult rv;
- ScopedXPCOMStartup xpcom;
- rv = xpcom.Initialize();
- NS_ENSURE_SUCCESS(rv, rv);
- mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
- rv = xpcom.SetWindowCreator(aNative);
- NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
- { //extra scoping is needed so we release these components before xpcom shutdown
- nsCOMPtr<nsIStringBundleService> sbs =
- mozilla::services::GetStringBundleService();
- NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
- nsCOMPtr<nsIStringBundle> sb;
- sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
- NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
- NS_ConvertUTF8toUTF16 appName(gAppData->name);
- const char16_t* params[] = {appName.get(), appName.get()};
- nsXPIDLString killMessage;
- sb->FormatStringFromName(aUnlocker ? u"restartMessageUnlocker"
- : u"restartMessageNoUnlocker",
- params, 2, getter_Copies(killMessage));
- nsXPIDLString killTitle;
- sb->FormatStringFromName(u"restartTitle",
- params, 1, getter_Copies(killTitle));
- if (!killMessage || !killTitle)
- return NS_ERROR_FAILURE;
- nsCOMPtr<nsIPromptService> ps
- (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
- NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
- if (aUnlocker) {
- int32_t button;
- const uint32_t flags =
- (nsIPromptService::BUTTON_TITLE_IS_STRING *
- nsIPromptService::BUTTON_POS_0) +
- (nsIPromptService::BUTTON_TITLE_CANCEL *
- nsIPromptService::BUTTON_POS_1);
- bool checkState = false;
- rv = ps->ConfirmEx(nullptr, killTitle, killMessage, flags,
- killTitle, nullptr, nullptr, nullptr,
- &checkState, &button);
- NS_ENSURE_SUCCESS_LOG(rv, rv);
- if (button == 0) {
- rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);
- if (NS_FAILED(rv)) {
- return rv;
- }
- SaveFileToEnv("XRE_PROFILE_PATH", aProfileDir);
- SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", aProfileLocalDir);
- return LaunchChild(aNative);
- }
- } else {
- rv = ps->Alert(nullptr, killTitle, killMessage);
- NS_ENSURE_SUCCESS_LOG(rv, rv);
- }
- return NS_ERROR_ABORT;
- }
- }
- static nsresult
- ProfileMissingDialog(nsINativeAppSupport* aNative)
- {
- nsresult rv;
- ScopedXPCOMStartup xpcom;
- rv = xpcom.Initialize();
- NS_ENSURE_SUCCESS(rv, rv);
- rv = xpcom.SetWindowCreator(aNative);
- NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
- { //extra scoping is needed so we release these components before xpcom shutdown
- nsCOMPtr<nsIStringBundleService> sbs =
- mozilla::services::GetStringBundleService();
- NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE);
- nsCOMPtr<nsIStringBundle> sb;
- sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
- NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
- NS_ConvertUTF8toUTF16 appName(gAppData->name);
- const char16_t* params[] = {appName.get(), appName.get()};
- nsXPIDLString missingMessage;
- // profileMissing
- sb->FormatStringFromName(u"profileMissing", params, 2, getter_Copies(missingMessage));
- nsXPIDLString missingTitle;
- sb->FormatStringFromName(u"profileMissingTitle",
- params, 1, getter_Copies(missingTitle));
- if (missingMessage && missingTitle) {
- nsCOMPtr<nsIPromptService> ps
- (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
- NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
- ps->Alert(nullptr, missingTitle, missingMessage);
- }
- return NS_ERROR_ABORT;
- }
- }
- static nsresult
- ProfileLockedDialog(nsIToolkitProfile* aProfile, nsIProfileUnlocker* aUnlocker,
- nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
- {
- nsCOMPtr<nsIFile> profileDir;
- nsresult rv = aProfile->GetRootDir(getter_AddRefs(profileDir));
- if (NS_FAILED(rv)) return rv;
- bool exists;
- profileDir->Exists(&exists);
- if (!exists) {
- return ProfileMissingDialog(aNative);
- }
- nsCOMPtr<nsIFile> profileLocalDir;
- rv = aProfile->GetLocalDir(getter_AddRefs(profileLocalDir));
- if (NS_FAILED(rv)) return rv;
- return ProfileLockedDialog(profileDir, profileLocalDir, aUnlocker, aNative,
- aResult);
- }
- static const char kProfileManagerURL[] =
- "chrome://mozapps/content/profile/profileSelection.xul";
- static ReturnAbortOnError
- ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
- nsINativeAppSupport* aNative)
- {
- if (!CanShowProfileManager()) {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
- nsresult rv;
- nsCOMPtr<nsIFile> profD, profLD;
- char16_t* profileNamePtr;
- nsAutoCString profileName;
- {
- ScopedXPCOMStartup xpcom;
- rv = xpcom.Initialize();
- NS_ENSURE_SUCCESS(rv, rv);
- // Initialize the graphics prefs, some of the paths need them before
- // any other graphics is initialized (e.g., showing the profile chooser.)
- gfxPrefs::GetSingleton();
- rv = xpcom.SetWindowCreator(aNative);
- NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
- #ifdef XP_WIN
- // we don't have to wait here because profile manager window will pump
- // and DDE message will be handled
- ProcessDDE(aNative, false);
- #endif
- { //extra scoping is needed so we release these components before xpcom shutdown
- nsCOMPtr<nsIWindowWatcher> windowWatcher
- (do_GetService(NS_WINDOWWATCHER_CONTRACTID));
- nsCOMPtr<nsIDialogParamBlock> ioParamBlock
- (do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID));
- nsCOMPtr<nsIMutableArray> dlgArray (do_CreateInstance(NS_ARRAY_CONTRACTID));
- NS_ENSURE_TRUE(windowWatcher && ioParamBlock && dlgArray, NS_ERROR_FAILURE);
- ioParamBlock->SetObjects(dlgArray);
- nsCOMPtr<nsIAppStartup> appStartup
- (do_GetService(NS_APPSTARTUP_CONTRACTID));
- NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
- nsCOMPtr<mozIDOMWindowProxy> newWindow;
- rv = windowWatcher->OpenWindow(nullptr,
- kProfileManagerURL,
- "_blank",
- "centerscreen,chrome,modal,titlebar",
- ioParamBlock,
- getter_AddRefs(newWindow));
- NS_ENSURE_SUCCESS_LOG(rv, rv);
- aProfileSvc->Flush();
- int32_t dialogConfirmed;
- rv = ioParamBlock->GetInt(0, &dialogConfirmed);
- if (NS_FAILED(rv) || dialogConfirmed == 0) return NS_ERROR_ABORT;
- nsCOMPtr<nsIProfileLock> lock;
- rv = dlgArray->QueryElementAt(0, NS_GET_IID(nsIProfileLock),
- getter_AddRefs(lock));
- NS_ENSURE_SUCCESS_LOG(rv, rv);
- rv = lock->GetDirectory(getter_AddRefs(profD));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = lock->GetLocalDirectory(getter_AddRefs(profLD));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = ioParamBlock->GetString(0, &profileNamePtr);
- NS_ENSURE_SUCCESS(rv, rv);
- CopyUTF16toUTF8(profileNamePtr, profileName);
- free(profileNamePtr);
- lock->Unlock();
- }
- }
- SaveFileToEnv("XRE_PROFILE_PATH", profD);
- SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
- SaveWordToEnv("XRE_PROFILE_NAME", profileName);
- bool offline = false;
- aProfileSvc->GetStartOffline(&offline);
- if (offline) {
- SaveToEnv("XRE_START_OFFLINE=1");
- }
- return LaunchChild(aNative);
- }
- /**
- * Get the currently running profile using its root directory.
- *
- * @param aProfileSvc The profile service
- * @param aCurrentProfileRoot The root directory of the current profile.
- * @param aProfile Out-param that returns the profile object.
- * @return an error if aCurrentProfileRoot is not found
- */
- static nsresult
- GetCurrentProfile(nsIToolkitProfileService* aProfileSvc,
- nsIFile* aCurrentProfileRoot,
- nsIToolkitProfile** aProfile)
- {
- NS_ENSURE_ARG_POINTER(aProfileSvc);
- NS_ENSURE_ARG_POINTER(aProfile);
- nsCOMPtr<nsISimpleEnumerator> profiles;
- nsresult rv = aProfileSvc->GetProfiles(getter_AddRefs(profiles));
- if (NS_FAILED(rv))
- return rv;
- bool foundMatchingProfile = false;
- nsCOMPtr<nsISupports> supports;
- rv = profiles->GetNext(getter_AddRefs(supports));
- while (NS_SUCCEEDED(rv)) {
- nsCOMPtr<nsIToolkitProfile> profile = do_QueryInterface(supports);
- nsCOMPtr<nsIFile> profileRoot;
- profile->GetRootDir(getter_AddRefs(profileRoot));
- profileRoot->Equals(aCurrentProfileRoot, &foundMatchingProfile);
- if (foundMatchingProfile) {
- profile.forget(aProfile);
- return NS_OK;
- }
- rv = profiles->GetNext(getter_AddRefs(supports));
- }
- return rv;
- }
- static bool gDoMigration = false;
- static bool gDoProfileReset = false;
- static nsAutoCString gResetOldProfileName;
- // Pick a profile. We need to end up with a profile lock.
- //
- // 1) check for --profile <path>
- // 2) check for -P <name>
- // 3) check for --ProfileManager
- // 4) use the default profile, if there is one
- // 5) if there are *no* profiles, set up profile-migration
- // 6) display the profile-manager UI
- static nsresult
- SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative,
- bool* aStartOffline, nsACString* aProfileName)
- {
- StartupTimeline::Record(StartupTimeline::SELECT_PROFILE);
- nsresult rv;
- ArgResult ar;
- const char* arg;
- *aResult = nullptr;
- *aStartOffline = false;
- ar = CheckArg("offline", true);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR, "Error: argument --offline is invalid when argument --osint is specified\n");
- return NS_ERROR_FAILURE;
- }
- if (ar || EnvHasValue("XRE_START_OFFLINE"))
- *aStartOffline = true;
- if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
- gDoProfileReset = true;
- gDoMigration = true;
- SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
- }
- // reset-profile and migration args need to be checked before any profiles are chosen below.
- ar = CheckArg("reset-profile", true);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR, "Error: argument --reset-profile is invalid when argument --osint is specified\n");
- return NS_ERROR_FAILURE;
- } else if (ar == ARG_FOUND) {
- gDoProfileReset = true;
- }
- ar = CheckArg("migration", true);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR, "Error: argument --migration is invalid when argument --osint is specified\n");
- return NS_ERROR_FAILURE;
- } else if (ar == ARG_FOUND) {
- gDoMigration = true;
- }
- nsCOMPtr<nsIFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
- if (lf) {
- nsCOMPtr<nsIFile> localDir =
- GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
- if (!localDir) {
- localDir = lf;
- }
- arg = PR_GetEnv("XRE_PROFILE_NAME");
- if (arg && *arg && aProfileName) {
- aProfileName->Assign(nsDependentCString(arg));
- if (gDoProfileReset) {
- gResetOldProfileName.Assign(*aProfileName);
- }
- }
- // Clear out flags that we handled (or should have handled!) last startup.
- const char *dummy;
- CheckArg("p", false, &dummy);
- CheckArg("profile", false, &dummy);
- CheckArg("profilemanager");
- if (gDoProfileReset) {
- // If we're resetting a profile, create a new one and use it to startup.
- nsCOMPtr<nsIToolkitProfile> newProfile;
- rv = CreateResetProfile(aProfileSvc, gResetOldProfileName, getter_AddRefs(newProfile));
- if (NS_SUCCEEDED(rv)) {
- rv = newProfile->GetRootDir(getter_AddRefs(lf));
- NS_ENSURE_SUCCESS(rv, rv);
- SaveFileToEnv("XRE_PROFILE_PATH", lf);
- rv = newProfile->GetLocalDir(getter_AddRefs(localDir));
- NS_ENSURE_SUCCESS(rv, rv);
- SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", localDir);
- rv = newProfile->GetName(*aProfileName);
- if (NS_FAILED(rv))
- aProfileName->Truncate(0);
- SaveWordToEnv("XRE_PROFILE_NAME", *aProfileName);
- } else {
- NS_WARNING("Profile reset failed.");
- gDoProfileReset = false;
- }
- }
- return NS_LockProfilePath(lf, localDir, nullptr, aResult);
- }
- ar = CheckArg("profile", true, &arg);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR, "Error: argument --profile requires a path\n");
- return NS_ERROR_FAILURE;
- }
- if (ar) {
- if (gDoProfileReset) {
- NS_WARNING("Profile reset is not supported in conjunction with --profile.");
- gDoProfileReset = false;
- }
- nsCOMPtr<nsIFile> lf;
- rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf));
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIProfileUnlocker> unlocker;
- // Check if the profile path exists and it's a directory.
- bool exists;
- lf->Exists(&exists);
- if (!exists) {
- rv = lf->Create(nsIFile::DIRECTORY_TYPE, 0700);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // If a profile path is specified directory on the command line, then
- // assume that the temp directory is the same as the given directory.
- rv = NS_LockProfilePath(lf, lf, getter_AddRefs(unlocker), aResult);
- if (NS_SUCCEEDED(rv))
- return rv;
- return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
- }
- ar = CheckArg("createprofile", true, &arg);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR, "Error: argument --createprofile requires a profile name\n");
- return NS_ERROR_FAILURE;
- }
- if (ar) {
- nsCOMPtr<nsIToolkitProfile> profile;
- const char* delim = strchr(arg, ' ');
- if (delim) {
- nsCOMPtr<nsIFile> lf;
- rv = NS_NewNativeLocalFile(nsDependentCString(delim + 1),
- true, getter_AddRefs(lf));
- if (NS_FAILED(rv)) {
- PR_fprintf(PR_STDERR, "Error: profile path not valid.\n");
- return rv;
- }
- // As with --profile, assume that the given path will be used for the
- // main profile directory.
- rv = aProfileSvc->CreateProfile(lf, nsDependentCSubstring(arg, delim),
- getter_AddRefs(profile));
- } else {
- rv = aProfileSvc->CreateProfile(nullptr, nsDependentCString(arg),
- getter_AddRefs(profile));
- }
- // Some pathological arguments can make it this far
- if (NS_FAILED(rv)) {
- PR_fprintf(PR_STDERR, "Error creating profile.\n");
- return rv;
- }
- rv = NS_ERROR_ABORT;
- aProfileSvc->Flush();
- // XXXben need to ensure prefs.js exists here so the tinderboxes will
- // not go orange.
- nsCOMPtr<nsIFile> prefsJSFile;
- profile->GetRootDir(getter_AddRefs(prefsJSFile));
- prefsJSFile->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
- nsAutoCString pathStr;
- prefsJSFile->GetNativePath(pathStr);
- PR_fprintf(PR_STDERR, "Success: created profile '%s' at '%s'\n", arg, pathStr.get());
- bool exists;
- prefsJSFile->Exists(&exists);
- if (!exists) {
- // Ignore any errors; we're about to return NS_ERROR_ABORT anyway.
- Unused << prefsJSFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
- }
- // XXXdarin perhaps 0600 would be better?
- return rv;
- }
- uint32_t count;
- rv = aProfileSvc->GetProfileCount(&count);
- NS_ENSURE_SUCCESS(rv, rv);
- ar = CheckArg("p", false, &arg);
- if (ar == ARG_BAD) {
- ar = CheckArg("osint");
- if (ar == ARG_FOUND) {
- PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument --osint is specified\n");
- return NS_ERROR_FAILURE;
- }
- if (CanShowProfileManager()) {
- return ShowProfileManager(aProfileSvc, aNative);
- }
- }
- if (ar) {
- ar = CheckArg("osint");
- if (ar == ARG_FOUND) {
- PR_fprintf(PR_STDERR, "Error: argument -p is invalid when argument --osint is specified\n");
- return NS_ERROR_FAILURE;
- }
- nsCOMPtr<nsIToolkitProfile> profile;
- rv = aProfileSvc->GetProfileByName(nsDependentCString(arg),
- getter_AddRefs(profile));
- if (NS_SUCCEEDED(rv)) {
- if (gDoProfileReset) {
- {
- // Check that the source profile is not in use by temporarily acquiring its lock.
- nsIProfileLock* tempProfileLock;
- nsCOMPtr<nsIProfileUnlocker> unlocker;
- rv = profile->Lock(getter_AddRefs(unlocker), &tempProfileLock);
- if (NS_FAILED(rv))
- return ProfileLockedDialog(profile, unlocker, aNative, &tempProfileLock);
- }
- nsresult gotName = profile->GetName(gResetOldProfileName);
- if (NS_SUCCEEDED(gotName)) {
- nsCOMPtr<nsIToolkitProfile> newProfile;
- rv = CreateResetProfile(aProfileSvc, gResetOldProfileName, getter_AddRefs(newProfile));
- if (NS_FAILED(rv)) {
- NS_WARNING("Failed to create a profile to reset to.");
- gDoProfileReset = false;
- } else {
- profile = newProfile;
- }
- } else {
- NS_WARNING("Failed to get the name of the profile we're resetting, so aborting reset.");
- gResetOldProfileName.Truncate(0);
- gDoProfileReset = false;
- }
- }
- nsCOMPtr<nsIProfileUnlocker> unlocker;
- rv = profile->Lock(getter_AddRefs(unlocker), aResult);
- if (NS_SUCCEEDED(rv)) {
- if (aProfileName)
- aProfileName->Assign(nsDependentCString(arg));
- return NS_OK;
- }
- return ProfileLockedDialog(profile, unlocker, aNative, aResult);
- }
- if (CanShowProfileManager()) {
- return ShowProfileManager(aProfileSvc, aNative);
- }
- }
- ar = CheckArg("profilemanager", true);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR, "Error: argument --profilemanager is invalid when argument --osint is specified\n");
- return NS_ERROR_FAILURE;
- } else if (ar == ARG_FOUND && CanShowProfileManager()) {
- return ShowProfileManager(aProfileSvc, aNative);
- }
- // Dev edition leftovers:
- // If the only existing profile is the dev-edition-profile,
- // then no valid profiles were found.
- if (count == 1) {
- nsCOMPtr<nsIToolkitProfile> deProfile;
- // GetSelectedProfile will auto-select the only profile if there's just one
- aProfileSvc->GetSelectedProfile(getter_AddRefs(deProfile));
- nsAutoCString profileName;
- deProfile->GetName(profileName);
- if (profileName.EqualsLiteral("dev-edition-default")) {
- count = 0;
- }
- }
- if (!count) {
- gDoMigration = true;
- gDoProfileReset = false;
- // create a default profile
- nsCOMPtr<nsIToolkitProfile> profile;
- nsresult rv = aProfileSvc->CreateProfile(nullptr, // choose a default dir for us
- NS_LITERAL_CSTRING("default"),
- getter_AddRefs(profile));
- if (NS_SUCCEEDED(rv)) {
- aProfileSvc->SetDefaultProfile(profile);
- aProfileSvc->Flush();
- rv = profile->Lock(nullptr, aResult);
- if (NS_SUCCEEDED(rv)) {
- if (aProfileName)
- aProfileName->AssignLiteral("default");
- return NS_OK;
- }
- }
- }
- bool useDefault = true;
- if (count > 1 && CanShowProfileManager()) {
- aProfileSvc->GetStartWithLastProfile(&useDefault);
- }
- if (useDefault) {
- nsCOMPtr<nsIToolkitProfile> profile;
- // GetSelectedProfile will auto-select the only profile if there's just one
- aProfileSvc->GetSelectedProfile(getter_AddRefs(profile));
- if (profile) {
- // If we're resetting a profile, create a new one and use it to startup.
- if (gDoProfileReset) {
- {
- // Check that the source profile is not in use by temporarily acquiring its lock.
- nsIProfileLock* tempProfileLock;
- nsCOMPtr<nsIProfileUnlocker> unlocker;
- rv = profile->Lock(getter_AddRefs(unlocker), &tempProfileLock);
- if (NS_FAILED(rv))
- return ProfileLockedDialog(profile, unlocker, aNative, &tempProfileLock);
- }
- nsresult gotName = profile->GetName(gResetOldProfileName);
- if (NS_SUCCEEDED(gotName)) {
- nsCOMPtr<nsIToolkitProfile> newProfile;
- rv = CreateResetProfile(aProfileSvc, gResetOldProfileName, getter_AddRefs(newProfile));
- if (NS_FAILED(rv)) {
- NS_WARNING("Failed to create a profile to reset to.");
- gDoProfileReset = false;
- }
- else {
- profile = newProfile;
- }
- }
- else {
- NS_WARNING("Failed to get the name of the profile we're resetting, so aborting reset.");
- gResetOldProfileName.Truncate(0);
- gDoProfileReset = false;
- }
- }
- // If you close Firefox and very quickly reopen it, the old Firefox may
- // still be closing down. Rather than immediately showing the
- // "Firefox is running but is not responding" message, we spend a few
- // seconds retrying first.
- static const int kLockRetrySeconds = 5;
- static const int kLockRetrySleepMS = 100;
- nsCOMPtr<nsIProfileUnlocker> unlocker;
- const TimeStamp start = TimeStamp::Now();
- do {
- rv = profile->Lock(getter_AddRefs(unlocker), aResult);
- if (NS_SUCCEEDED(rv)) {
- StartupTimeline::Record(StartupTimeline::AFTER_PROFILE_LOCKED);
- // Try to grab the profile name.
- if (aProfileName) {
- rv = profile->GetName(*aProfileName);
- if (NS_FAILED(rv))
- aProfileName->Truncate(0);
- }
- return NS_OK;
- }
- PR_Sleep(kLockRetrySleepMS);
- } while (TimeStamp::Now() - start < TimeDuration::FromSeconds(kLockRetrySeconds));
- return ProfileLockedDialog(profile, unlocker, aNative, aResult);
- }
- }
- if (!CanShowProfileManager()) {
- return NS_ERROR_FAILURE;
- }
- return ShowProfileManager(aProfileSvc, aNative);
- }
- /**
- * Checks the compatibility.ini file to see if we have updated our application
- * or otherwise invalidated our caches. If the application has been updated,
- * we return false; otherwise, we return true. We also write the status
- * of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
- * is always invalid if the application has been updated.
- */
- static bool
- CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
- const nsCString& aOSABI, nsIFile* aXULRunnerDir,
- nsIFile* aAppDir, nsIFile* aFlagFile,
- bool* aCachesOK)
- {
- *aCachesOK = false;
- nsCOMPtr<nsIFile> file;
- aProfileDir->Clone(getter_AddRefs(file));
- if (!file)
- return false;
- file->AppendNative(FILE_COMPATIBILITY_INFO);
- nsINIParser parser;
- nsresult rv = parser.Init(file);
- if (NS_FAILED(rv))
- return false;
- nsAutoCString buf;
- rv = parser.GetString("Compatibility", "LastVersion", buf);
- if (NS_FAILED(rv) || !aVersion.Equals(buf))
- return false;
- rv = parser.GetString("Compatibility", "LastOSABI", buf);
- if (NS_FAILED(rv) || !aOSABI.Equals(buf))
- return false;
- rv = parser.GetString("Compatibility", "LastPlatformDir", buf);
- if (NS_FAILED(rv))
- return false;
- nsCOMPtr<nsIFile> lf;
- rv = NS_NewNativeLocalFile(buf, false,
- getter_AddRefs(lf));
- if (NS_FAILED(rv))
- return false;
- bool eq;
- rv = lf->Equals(aXULRunnerDir, &eq);
- if (NS_FAILED(rv) || !eq)
- return false;
- if (aAppDir) {
- rv = parser.GetString("Compatibility", "LastAppDir", buf);
- if (NS_FAILED(rv))
- return false;
- rv = NS_NewNativeLocalFile(buf, false,
- getter_AddRefs(lf));
- if (NS_FAILED(rv))
- return false;
- rv = lf->Equals(aAppDir, &eq);
- if (NS_FAILED(rv) || !eq)
- return false;
- }
- // If we see this flag, caches are invalid.
- rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
- *aCachesOK = (NS_FAILED(rv) || !buf.EqualsLiteral("1"));
- bool purgeCaches = false;
- if (aFlagFile) {
- aFlagFile->Exists(&purgeCaches);
- }
- *aCachesOK = !purgeCaches && *aCachesOK;
- return true;
- }
- static void BuildVersion(nsCString &aBuf)
- {
- aBuf.Assign(gAppData->version);
- aBuf.Append('_');
- aBuf.Append(gAppData->buildID);
- aBuf.Append('/');
- aBuf.Append(gToolkitBuildID);
- }
- static void
- WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
- const nsCString& aOSABI, nsIFile* aXULRunnerDir,
- nsIFile* aAppDir, bool invalidateCache)
- {
- nsCOMPtr<nsIFile> file;
- aProfileDir->Clone(getter_AddRefs(file));
- if (!file)
- return;
- file->AppendNative(FILE_COMPATIBILITY_INFO);
- nsAutoCString platformDir;
- aXULRunnerDir->GetNativePath(platformDir);
- nsAutoCString appDir;
- if (aAppDir)
- aAppDir->GetNativePath(appDir);
- PRFileDesc *fd;
- nsresult rv =
- file->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
- if (NS_FAILED(rv)) {
- NS_ERROR("could not create output stream");
- return;
- }
- static const char kHeader[] = "[Compatibility]" NS_LINEBREAK
- "LastVersion=";
- PR_Write(fd, kHeader, sizeof(kHeader) - 1);
- PR_Write(fd, aVersion.get(), aVersion.Length());
- static const char kOSABIHeader[] = NS_LINEBREAK "LastOSABI=";
- PR_Write(fd, kOSABIHeader, sizeof(kOSABIHeader) - 1);
- PR_Write(fd, aOSABI.get(), aOSABI.Length());
- static const char kPlatformDirHeader[] = NS_LINEBREAK "LastPlatformDir=";
- PR_Write(fd, kPlatformDirHeader, sizeof(kPlatformDirHeader) - 1);
- PR_Write(fd, platformDir.get(), platformDir.Length());
- static const char kAppDirHeader[] = NS_LINEBREAK "LastAppDir=";
- if (aAppDir) {
- PR_Write(fd, kAppDirHeader, sizeof(kAppDirHeader) - 1);
- PR_Write(fd, appDir.get(), appDir.Length());
- }
- static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1";
- if (invalidateCache)
- PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
- static const char kNL[] = NS_LINEBREAK;
- PR_Write(fd, kNL, sizeof(kNL) - 1);
- PR_Close(fd);
- }
- /**
- * Returns true if the startup cache file was successfully removed.
- * Returns false if file->Clone fails at any point (OOM) or if unable
- * to remove the startup cache file. Note in particular the return value
- * is unaffected by a failure to remove extensions.ini
- */
- static bool
- RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfileDir,
- bool aRemoveEMFiles)
- {
- nsCOMPtr<nsIFile> file;
- aProfileDir->Clone(getter_AddRefs(file));
- if (!file)
- return false;
- if (aRemoveEMFiles) {
- file->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));
- file->Remove(false);
- }
- aLocalProfileDir->Clone(getter_AddRefs(file));
- if (!file)
- return false;
- #if defined(XP_UNIX)
- #define PLATFORM_FASL_SUFFIX ".mfasl"
- #elif defined(XP_WIN)
- #define PLATFORM_FASL_SUFFIX ".mfl"
- #endif
- file->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX));
- file->Remove(false);
- file->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX));
- file->Remove(false);
- file->SetNativeLeafName(NS_LITERAL_CSTRING("startupCache"));
- nsresult rv = file->Remove(true);
- return NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
- }
- // To support application initiated restart via nsIAppStartup.quit, we
- // need to save various environment variables, and then restore them
- // before re-launching the application.
- static struct SavedVar {
- const char *name;
- char *value;
- } gSavedVars[] = {
- {"XUL_APP_FILE", nullptr}
- };
- static void SaveStateForAppInitiatedRestart()
- {
- for (size_t i = 0; i < ArrayLength(gSavedVars); ++i) {
- const char *s = PR_GetEnv(gSavedVars[i].name);
- if (s)
- gSavedVars[i].value = PR_smprintf("%s=%s", gSavedVars[i].name, s);
- }
- }
- static void RestoreStateForAppInitiatedRestart()
- {
- for (size_t i = 0; i < ArrayLength(gSavedVars); ++i) {
- if (gSavedVars[i].value)
- PR_SetEnv(gSavedVars[i].value);
- }
- }
- const nsXREAppData* gAppData = nullptr;
- #ifdef MOZ_WIDGET_GTK
- static void MOZ_gdk_display_close(GdkDisplay *display)
- {
- #if CLEANUP_MEMORY
- // XXX wallpaper for bug 417163: don't close the Display if we're using the
- // Qt theme because we crash (in Qt code) when using jemalloc.
- bool skip_display_close = false;
- GtkSettings* settings =
- gtk_settings_get_for_screen(gdk_display_get_default_screen(display));
- gchar *theme_name;
- g_object_get(settings, "gtk-theme-name", &theme_name, nullptr);
- if (theme_name) {
- skip_display_close = strcmp(theme_name, "Qt") == 0;
- if (skip_display_close)
- NS_WARNING("wallpaper bug 417163 for Qt theme");
- g_free(theme_name);
- }
- #if (MOZ_WIDGET_GTK == 3)
- // A workaround for https://bugzilla.gnome.org/show_bug.cgi?id=703257
- if (gtk_check_version(3,9,8) != NULL)
- skip_display_close = true;
- #endif
- // Get a (new) Pango context that holds a reference to the fontmap that
- // GTK has been using. gdk_pango_context_get() must be called while GTK
- // has a default display.
- PangoContext *pangoContext = gdk_pango_context_get();
- bool buggyCairoShutdown = cairo_version() < CAIRO_VERSION_ENCODE(1, 4, 0);
- if (!buggyCairoShutdown) {
- // We should shut down GDK before we shut down libraries it depends on
- // like Pango and cairo. But if cairo shutdown is buggy, we should
- // shut down cairo first otherwise it may crash because of dangling
- // references to Display objects (see bug 469831).
- if (!skip_display_close)
- gdk_display_close(display);
- }
- // Clean up PangoCairo's default fontmap.
- // This pango_fc_font_map_shutdown call (and the associated code to
- // get the font map) really shouldn't be needed anymore, except that
- // it's needed to avoid having cairo_debug_reset_static_data fatally
- // assert if we've leaked other things that hold on to the fontmap,
- // which is something that currently happens in mochitest-plugins.
- // Even if it didn't happen in mochitest-plugins, we probably want to
- // avoid the crash-on-leak problem since it makes it harder to use
- // many of our leak tools to debug leaks.
- // This doesn't take a reference.
- PangoFontMap *fontmap = pango_context_get_font_map(pangoContext);
- // Do some shutdown of the fontmap, which releases the fonts, clearing a
- // bunch of circular references from the fontmap through the fonts back to
- // itself. The shutdown that this does is much less than what's done by
- // the fontmap's finalize, though.
- if (PANGO_IS_FC_FONT_MAP(fontmap))
- pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(fontmap));
- g_object_unref(pangoContext);
- // Tell PangoCairo to release its default fontmap.
- pango_cairo_font_map_set_default(nullptr);
- // cairo_debug_reset_static_data() is prototyped through cairo.h included
- // by gtk.h.
- #ifdef cairo_debug_reset_static_data
- #error "Looks like we're including Mozilla's cairo instead of system cairo"
- #endif
- cairo_debug_reset_static_data();
- // FIXME: Do we need to call this in non-GTK2 cases as well?
- FcFini();
- if (buggyCairoShutdown) {
- if (!skip_display_close)
- gdk_display_close(display);
- }
- #else // not CLEANUP_MEMORY
- // Don't do anything to avoid running into driver bugs under XCloseDisplay().
- // See bug 973192.
- (void) display;
- #endif
- }
- static const char* detectDisplay(void)
- {
- bool tryX11 = false;
- bool tryWayland = false;
- bool tryBroadway = false;
- // Honor user backend selection
- const char *backend = PR_GetEnv("GDK_BACKEND");
- if (!backend || strstr(backend, "*")) {
- // Try all backends
- tryX11 = true;
- tryWayland = true;
- tryBroadway = true;
- } else if (backend) {
- if (strstr(backend, "x11"))
- tryX11 = true;
- if (strstr(backend, "wayland"))
- tryWayland = true;
- if (strstr(backend, "broadway"))
- tryBroadway = true;
- }
- const char *display_name;
- if (tryX11 && (display_name = PR_GetEnv("DISPLAY"))) {
- return display_name;
- } else if (tryWayland && (display_name = PR_GetEnv("WAYLAND_DISPLAY"))) {
- return display_name;
- } else if (tryBroadway && (display_name = PR_GetEnv("BROADWAY_DISPLAY"))) {
- return display_name;
- }
- PR_fprintf(PR_STDERR, "Error: GDK_BACKEND does not match available displays\n");
- return nullptr;
- }
- #endif // MOZ_WIDGET_GTK
- /**
- * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
- * the process and use it to determine whether the application defines its own
- * memory allocator or not.
- *
- * Since most applications (e.g. Firefox and Thunderbird) don't use any special
- * allocators and therefore don't define this symbol, NSPR must search the
- * entire process, which reduces startup performance.
- *
- * By defining the symbol here, we can avoid the wasted lookup and hopefully
- * improve startup performance.
- */
- NS_VISIBILITY_DEFAULT PRBool nspr_use_zone_allocator = PR_FALSE;
- #ifdef CAIRO_HAS_DWRITE_FONT
- #include <dwrite.h>
- #include "nsWindowsHelpers.h"
- #ifdef DEBUG_DWRITE_STARTUP
- #define LOGREGISTRY(msg) LogRegistryEvent(msg)
- // for use when monitoring process
- static void LogRegistryEvent(const wchar_t *msg)
- {
- HKEY dummyKey;
- HRESULT hr;
- wchar_t buf[512];
- wsprintf(buf, L" log %s", msg);
- hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey);
- if (SUCCEEDED(hr)) {
- RegCloseKey(dummyKey);
- }
- }
- #else
- #define LOGREGISTRY(msg)
- #endif
- static DWORD WINAPI InitDwriteBG(LPVOID lpdwThreadParam)
- {
- SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);
- LOGREGISTRY(L"loading dwrite.dll");
- HMODULE dwdll = LoadLibrarySystem32(L"dwrite.dll");
- if (dwdll) {
- decltype(DWriteCreateFactory)* createDWriteFactory = (decltype(DWriteCreateFactory)*)
- GetProcAddress(dwdll, "DWriteCreateFactory");
- if (createDWriteFactory) {
- LOGREGISTRY(L"creating dwrite factory");
- IDWriteFactory *factory;
- HRESULT hr = createDWriteFactory(
- DWRITE_FACTORY_TYPE_SHARED,
- __uuidof(IDWriteFactory),
- reinterpret_cast<IUnknown**>(&factory));
- if (SUCCEEDED(hr)) {
- LOGREGISTRY(L"dwrite factory done");
- factory->Release();
- LOGREGISTRY(L"freed factory");
- } else {
- LOGREGISTRY(L"failed to create factory");
- }
- }
- }
- SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
- return 0;
- }
- #endif
- #ifdef USE_GLX_TEST
- bool fire_glxtest_process();
- #endif
- #include "GeckoProfiler.h"
- // Encapsulates startup and shutdown state for XRE_main
- class XREMain
- {
- public:
- XREMain() :
- mStartOffline(false)
- , mShuttingDown(false)
- #ifdef MOZ_ENABLE_XREMOTE
- , mDisableRemote(false)
- #endif
- #if defined(MOZ_WIDGET_GTK)
- , mGdkDisplay(nullptr)
- #endif
- {};
- ~XREMain() {
- mScopedXPCOM = nullptr;
- mAppData = nullptr;
- }
- int XRE_main(int argc, char* argv[], const nsXREAppData* aAppData);
- int XRE_mainInit(bool* aExitFlag);
- int XRE_mainStartup(bool* aExitFlag);
- nsresult XRE_mainRun();
- nsCOMPtr<nsINativeAppSupport> mNativeApp;
- nsCOMPtr<nsIToolkitProfileService> mProfileSvc;
- nsCOMPtr<nsIFile> mProfD;
- nsCOMPtr<nsIFile> mProfLD;
- nsCOMPtr<nsIProfileLock> mProfileLock;
- #ifdef MOZ_ENABLE_XREMOTE
- nsCOMPtr<nsIRemoteService> mRemoteService;
- nsProfileLock mRemoteLock;
- nsCOMPtr<nsIFile> mRemoteLockDir;
- #endif
- UniquePtr<ScopedXPCOMStartup> mScopedXPCOM;
- nsAutoPtr<mozilla::ScopedAppData> mAppData;
- nsXREDirProvider mDirProvider;
- nsAutoCString mProfileName;
- nsAutoCString mDesktopStartupID;
- bool mStartOffline;
- bool mShuttingDown;
- #ifdef MOZ_ENABLE_XREMOTE
- bool mDisableRemote;
- #endif
- #if defined(MOZ_WIDGET_GTK)
- GdkDisplay* mGdkDisplay;
- #endif
- };
- /*
- * XRE_mainInit - Initial setup and command line parameter processing.
- * Main() will exit early if either return value != 0 or if aExitFlag is
- * true.
- */
- int
- XREMain::XRE_mainInit(bool* aExitFlag)
- {
- if (!aExitFlag)
- return 1;
- *aExitFlag = false;
- atexit(UnexpectedExit);
- auto expectedShutdown = mozilla::MakeScopeExit([&] {
- MozExpectedExit();
- });
- StartupTimeline::Record(StartupTimeline::MAIN);
- if (PR_GetEnv("MOZ_CHAOSMODE")) {
- ChaosFeature feature = ChaosFeature::Any;
- long featureInt = strtol(PR_GetEnv("MOZ_CHAOSMODE"), nullptr, 16);
- if (featureInt) {
- // NOTE: MOZ_CHAOSMODE=0 or a non-hex value maps to Any feature.
- feature = static_cast<ChaosFeature>(featureInt);
- }
- ChaosMode::SetChaosFeature(feature);
- }
- if (ChaosMode::isActive(ChaosFeature::Any)) {
- printf_stderr("*** You are running in chaos test mode. See ChaosMode.h. ***\n");
- }
- nsresult rv;
- ArgResult ar;
- #ifdef DEBUG
- if (PR_GetEnv("XRE_MAIN_BREAK"))
- NS_BREAK();
- #endif
- #ifdef USE_GLX_TEST
- // bug 639842 - it's very important to fire this process BEFORE we set up
- // error handling. indeed, this process is expected to be crashy, and we
- // don't want the user to see its crashes. That's the whole reason for
- // doing this in a separate process.
- //
- // This call will cause a fork and the fork will terminate itself separately
- // from the usual shutdown sequence
- fire_glxtest_process();
- #endif
- SetupErrorHandling(gArgv[0]);
- // Set up environment for NSS database choice
- #ifndef NSS_DISABLE_DBM
- // Allow iteration counts in DBM mode
- SaveToEnv("NSS_ALLOW_LEGACY_DBM_ITERATION_COUNT=1");
- #endif
- #ifdef DEBUG
- // Reduce the number of rounds for debug builds for perf/test reasons.
- SaveToEnv("NSS_MAX_MP_PBE_ITERATION_COUNT=15");
- #else
- #ifdef MOZ_SECURITY_SQLSTORE
- // We're using SQL; NSS's defaults for rounds are fine.
- #else
- // Set default Master Password rounds to a sane value for DBM which is slower
- // than SQL for PBKDF. The NSS hard-coded default of 10,000 is too much.
- // See also Bug 1606992 for perf issues.
- SaveToEnv("NSS_MAX_MP_PBE_ITERATION_COUNT=500");
- #endif
- #endif
- #ifdef CAIRO_HAS_DWRITE_FONT
- {
- // Bug 602792 - when DWriteCreateFactory is called the dwrite client dll
- // starts the FntCache service if it isn't already running (it's set
- // to manual startup by default in Windows 7 RTM). Subsequent DirectWrite
- // calls cause the IDWriteFactory object to communicate with the FntCache
- // service with a timeout; if there's no response after the timeout, the
- // DirectWrite client library will assume the service isn't around and do
- // manual font file I/O on _all_ system fonts. To avoid this, load the
- // dwrite library and create a factory as early as possible so that the
- // FntCache service is ready by the time it's needed.
- CreateThread(nullptr, 0, &InitDwriteBG, nullptr, 0, nullptr);
- }
- #endif
- #ifdef XP_UNIX
- const char *home = PR_GetEnv("HOME");
- if (!home || !*home) {
- struct passwd *pw = getpwuid(geteuid());
- if (!pw || !pw->pw_dir) {
- Output(true, "Could not determine HOME directory");
- return 1;
- }
- SaveWordToEnv("HOME", nsDependentCString(pw->pw_dir));
- }
- #endif
- #ifdef MOZ_ACCESSIBILITY_ATK
- // Suppress atk-bridge init at startup, until mozilla accessibility is
- // initialized. This works after gnome 2.24.2.
- SaveToEnv("NO_AT_BRIDGE=1");
- #endif
- // Check for application.ini overrides
- const char* override = nullptr;
- ar = CheckArg("override", true, &override);
- if (ar == ARG_BAD) {
- Output(true, "Incorrect number of arguments passed to --override");
- return 1;
- }
- else if (ar == ARG_FOUND) {
- nsCOMPtr<nsIFile> overrideLF;
- rv = XRE_GetFileFromPath(override, getter_AddRefs(overrideLF));
- if (NS_FAILED(rv)) {
- Output(true, "Error: unrecognized override.ini path.\n");
- return 1;
- }
- rv = XRE_ParseAppData(overrideLF, mAppData.get());
- if (NS_FAILED(rv)) {
- Output(true, "Couldn't read override.ini");
- return 1;
- }
- }
- // Check sanity and correctness of app data.
- if (!mAppData->name) {
- Output(true, "Error: App:Name not specified in application.ini\n");
- return 1;
- }
- if (!mAppData->buildID) {
- Output(true, "Error: App:BuildID not specified in application.ini\n");
- return 1;
- }
- // XXX Originally ScopedLogging was here? Now it's in XRE_main above
- // XRE_mainInit.
- if (!mAppData->xreDirectory) {
- nsCOMPtr<nsIFile> lf;
- rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
- if (NS_FAILED(rv))
- return 2;
- nsCOMPtr<nsIFile> greDir;
- rv = lf->GetParent(getter_AddRefs(greDir));
- if (NS_FAILED(rv))
- return 2;
- greDir.forget(&mAppData->xreDirectory);
- }
- if (!mAppData->directory) {
- NS_IF_ADDREF(mAppData->directory = mAppData->xreDirectory);
- }
- if (mAppData->size > offsetof(nsXREAppData, minVersion)) {
- if (!mAppData->minVersion) {
- Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
- return 1;
- }
- if (!mAppData->maxVersion) {
- // If no maxVersion is specified, we assume the app is only compatible
- // with the initial preview release. Do not increment this number ever!
- SetAllocatedString(mAppData->maxVersion, "1.*");
- }
- if (mozilla::Version(mAppData->minVersion) > gToolkitVersion ||
- mozilla::Version(mAppData->maxVersion) < gToolkitVersion) {
- Output(true, "Error: Platform version '%s' is not compatible with\n"
- "minVersion >= %s\nmaxVersion <= %s\n",
- gToolkitVersion,
- mAppData->minVersion, mAppData->maxVersion);
- return 1;
- }
- }
- rv = mDirProvider.Initialize(mAppData->directory, mAppData->xreDirectory);
- if (NS_FAILED(rv))
- return 1;
- SaveToEnv("MOZ_LAUNCHED_CHILD=");
- gRestartArgc = gArgc;
- gRestartArgv = (char**) malloc(sizeof(char*) * (gArgc + 1 + (override ? 2 : 0)));
- if (!gRestartArgv) {
- return 1;
- }
- int i;
- for (i = 0; i < gArgc; ++i) {
- gRestartArgv[i] = gArgv[i];
- }
- // Add the -override argument back (it is removed automatically be CheckArg) if there is one
- if (override) {
- gRestartArgv[gRestartArgc++] = const_cast<char*>("-override");
- gRestartArgv[gRestartArgc++] = const_cast<char*>(override);
- }
- gRestartArgv[gRestartArgc] = nullptr;
- if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
- gSafeMode = true;
- // unset the env variable
- SaveToEnv("MOZ_SAFE_MODE_RESTART=");
- }
- ar = CheckArg("safe-mode", true);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR, "Error: argument --safe-mode is invalid when argument --osint is specified\n");
- return 1;
- } else if (ar == ARG_FOUND) {
- gSafeMode = true;
- }
- #ifdef XP_WIN
- // If the shift key is pressed and the ctrl and / or alt keys are not pressed
- // during startup start in safe mode. GetKeyState returns a short and the high
- // order bit will be 1 if the key is pressed. By masking the returned short
- // with 0x8000 the result will be 0 if the key is not pressed and non-zero
- // otherwise.
- if ((GetKeyState(VK_SHIFT) & 0x8000) &&
- !(GetKeyState(VK_CONTROL) & 0x8000) &&
- !(GetKeyState(VK_MENU) & 0x8000) &&
- !EnvHasValue("MOZ_DISABLE_SAFE_MODE_KEY")) {
- gSafeMode = true;
- }
- #endif
- #ifdef XP_WIN
- {
- // Add CPU microcode version to the crash report as "CPUMicrocodeVersion".
- // It feels like this code may belong in nsSystemInfo instead.
- int cpuUpdateRevision = -1;
- HKEY key;
- static const WCHAR keyName[] =
- L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName , 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
- DWORD updateRevision[2];
- DWORD len = sizeof(updateRevision);
- DWORD vtype;
- // Windows 7 uses "Update Signature", 8 uses "Update Revision".
- // For AMD CPUs, "CurrentPatchLevel" is sometimes used.
- // Take the first one we find.
- LPCWSTR choices[] = {L"Update Signature", L"Update Revision", L"CurrentPatchLevel"};
- for (size_t oneChoice=0; oneChoice<ArrayLength(choices); oneChoice++) {
- if (RegQueryValueExW(key, choices[oneChoice],
- 0, &vtype,
- reinterpret_cast<LPBYTE>(updateRevision),
- &len) == ERROR_SUCCESS) {
- if (vtype == REG_BINARY && len == sizeof(updateRevision)) {
- // The first word is unused
- cpuUpdateRevision = static_cast<int>(updateRevision[1]);
- break;
- } else if (vtype == REG_DWORD && len == sizeof(updateRevision[0])) {
- cpuUpdateRevision = static_cast<int>(updateRevision[0]);
- break;
- }
- }
- }
- }
- }
- #endif
- // Handle --no-remote and --new-instance command line arguments. Setup
- // the environment to better accommodate other components and various
- // restart scenarios.
- ar = CheckArg("no-remote", true);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR, "Error: argument --no-remote is invalid when argument --osint is specified\n");
- return 1;
- } else if (ar == ARG_FOUND) {
- SaveToEnv("MOZ_NO_REMOTE=1");
- }
- ar = CheckArg("new-instance", true);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR, "Error: argument --new-instance is invalid when argument --osint is specified\n");
- return 1;
- } else if (ar == ARG_FOUND) {
- SaveToEnv("MOZ_NEW_INSTANCE=1");
- }
- // Handle --help and --version command line arguments.
- // They should return quickly, so we deal with them here.
- if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
- DumpHelp();
- *aExitFlag = true;
- return 0;
- }
- if (CheckArg("v") || CheckArg("version")) {
- DumpVersion();
- *aExitFlag = true;
- return 0;
- }
- rv = XRE_InitCommandLine(gArgc, gArgv);
- NS_ENSURE_SUCCESS(rv, 1);
- // Check for --register, which registers chrome and then exits immediately.
- ar = CheckArg("register", true);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR, "Error: argument --register is invalid when argument --osint is specified\n");
- return 1;
- } else if (ar == ARG_FOUND) {
- ScopedXPCOMStartup xpcom;
- rv = xpcom.Initialize();
- NS_ENSURE_SUCCESS(rv, 1);
- {
- nsCOMPtr<nsIChromeRegistry> chromeReg =
- mozilla::services::GetChromeRegistryService();
- NS_ENSURE_TRUE(chromeReg, 1);
- chromeReg->CheckForNewChrome();
- }
- *aExitFlag = true;
- return 0;
- }
- return 0;
- }
- namespace mozilla {
- ShutdownChecksMode gShutdownChecks = SCM_NOTHING;
- } // namespace mozilla
- static void SetShutdownChecks() {
- // Set default first. On debug builds we crash. On nightly and local
- // builds we record. Nightlies will then send the info via telemetry,
- // but it is usefull to have the data in about:telemetry in local builds
- // too.
- #ifdef DEBUG
- gShutdownChecks = SCM_CRASH;
- #else
- const char* releaseChannel = NS_STRINGIFY(MOZ_UPDATE_CHANNEL);
- if (strcmp(releaseChannel, "nightly") == 0 ||
- strcmp(releaseChannel, "default") == 0) {
- gShutdownChecks = SCM_RECORD;
- } else {
- gShutdownChecks = SCM_NOTHING;
- }
- #endif
- // We let an environment variable override the default so that addons
- // authors can use it for debugging shutdown with released firefox versions.
- const char* mozShutdownChecksEnv = PR_GetEnv("MOZ_SHUTDOWN_CHECKS");
- if (mozShutdownChecksEnv) {
- if (strcmp(mozShutdownChecksEnv, "crash") == 0) {
- gShutdownChecks = SCM_CRASH;
- } else if (strcmp(mozShutdownChecksEnv, "record") == 0) {
- gShutdownChecks = SCM_RECORD;
- } else if (strcmp(mozShutdownChecksEnv, "nothing") == 0) {
- gShutdownChecks = SCM_NOTHING;
- }
- }
- }
- /*
- * XRE_mainStartup - Initializes the profile and various other services.
- * Main() will exit early if either return value != 0 or if aExitFlag is
- * true.
- */
- int
- XREMain::XRE_mainStartup(bool* aExitFlag)
- {
- nsresult rv;
- if (!aExitFlag)
- return 1;
- *aExitFlag = false;
- SetShutdownChecks();
- // Enable Telemetry IO Reporting on DEBUG, nightly and local builds
- #ifdef DEBUG
- mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
- #else
- {
- const char* releaseChannel = NS_STRINGIFY(MOZ_UPDATE_CHANNEL);
- if (strcmp(releaseChannel, "nightly") == 0 ||
- strcmp(releaseChannel, "default") == 0) {
- mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
- }
- }
- #endif /* DEBUG */
- #if defined(MOZ_WIDGET_GTK) || defined(MOZ_ENABLE_XREMOTE)
- // Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear it.
- #define HAVE_DESKTOP_STARTUP_ID
- const char* desktopStartupIDEnv = PR_GetEnv("DESKTOP_STARTUP_ID");
- if (desktopStartupIDEnv) {
- mDesktopStartupID.Assign(desktopStartupIDEnv);
- }
- #endif
- #if defined(MOZ_WIDGET_GTK)
- // setup for private colormap. Ideally we'd like to do this
- // in nsAppShell::Create, but we need to get in before gtk
- // has been initialized to make sure everything is running
- // consistently.
- #if (MOZ_WIDGET_GTK == 2)
- if (CheckArg("install"))
- gdk_rgb_set_install(TRUE);
- #endif
- // Set program name to the one defined in application.ini.
- {
- nsAutoCString program(gAppData->name);
- ToLowerCase(program);
- g_set_prgname(program.get());
- }
- // Initialize GTK here for splash.
- #if (MOZ_WIDGET_GTK == 3) && defined(MOZ_X11)
- // Disable XInput2 support due to focus bugginess. See bugs 1182700, 1170342.
- const char* useXI2 = PR_GetEnv("MOZ_USE_XINPUT2");
- if (!useXI2 || (*useXI2 == '0'))
- gdk_disable_multidevice();
- #endif
- // Open the display ourselves instead of using gtk_init, so that we can
- // close it without fear that one day gtk might clean up the display it
- // opens.
- if (!gtk_parse_args(&gArgc, &gArgv))
- return 1;
- #endif /* MOZ_WIDGET_GTK */
- #ifdef LIBFUZZER
- if (PR_GetEnv("LIBFUZZER")) {
- *aExitFlag = true;
- return mozilla::libFuzzerRunner->Run();
- }
- #endif
- if (PR_GetEnv("MOZ_RUN_GTEST")) {
- int result;
- #ifdef XP_WIN
- UseParentConsole();
- #endif
- // RunGTest will only be set if we're in xul-unit
- if (mozilla::RunGTest) {
- gIsGtest = true;
- result = mozilla::RunGTest();
- gIsGtest = false;
- } else {
- result = 1;
- printf("TEST-UNEXPECTED-FAIL | gtest | Not compiled with enable-tests\n");
- }
- *aExitFlag = true;
- return result;
- }
- #if defined(MOZ_WIDGET_GTK)
- // display_name is owned by gdk.
- const char *display_name = gdk_get_display_arg_name();
- bool saveDisplayArg = false;
- if (display_name) {
- saveDisplayArg = true;
- } else {
- display_name = detectDisplay();
- if (!display_name) {
- return 1;
- }
- }
- #endif /* MOZ_WIDGET_GTK */
- #ifdef MOZ_X11
- // Init X11 in thread-safe mode. Must be called prior to the first call to XOpenDisplay
- // (called inside gdk_display_open). This is a requirement for off main tread compositing.
- XInitThreads();
- #endif
- #if defined(MOZ_WIDGET_GTK)
- mGdkDisplay = gdk_display_open(display_name);
- if (!mGdkDisplay) {
- PR_fprintf(PR_STDERR, "Error: cannot open display: %s\n", display_name);
- return 1;
- }
- gdk_display_manager_set_default_display (gdk_display_manager_get(),
- mGdkDisplay);
- if (GDK_IS_X11_DISPLAY(mGdkDisplay)) {
- if (saveDisplayArg) {
- SaveWordToEnv("DISPLAY", nsDependentCString(display_name));
- }
- } else {
- mDisableRemote = true;
- }
- #endif
- #ifdef MOZ_ENABLE_XREMOTE
- // handle --remote now that xpcom is fired up
- bool newInstance;
- {
- char *e = PR_GetEnv("MOZ_NO_REMOTE");
- mDisableRemote = (mDisableRemote || (e && *e));
- if (mDisableRemote) {
- newInstance = true;
- } else {
- e = PR_GetEnv("MOZ_NEW_INSTANCE");
- newInstance = (e && *e);
- }
- }
- if (!newInstance) {
- nsAutoCString program(gAppData->remotingName);
- ToLowerCase(program);
- const char* username = getenv("LOGNAME");
- const char* profile = nullptr;
- RemoteResult rr = ParseRemoteCommandLine(program, &profile, &username);
- if (rr == REMOTE_ARG_BAD) {
- return 1;
- }
- if (!username) {
- struct passwd *pw = getpwuid(geteuid());
- if (pw && pw->pw_name) {
- // Beware that another call to getpwent/getpwname/getpwuid will overwrite
- // pw, but we don't have such another call between here and when username
- // is used last.
- username = pw->pw_name;
- }
- }
- nsCOMPtr<nsIFile> mutexDir;
- rv = GetSpecialSystemDirectory(OS_TemporaryDirectory, getter_AddRefs(mutexDir));
- if (NS_SUCCEEDED(rv)) {
- nsAutoCString mutexPath = program + NS_LITERAL_CSTRING("_");
- // In the unlikely even that LOGNAME is not set and getpwuid failed, just
- // don't put the username in the mutex directory. It will conflict with
- // other users mutex, but the worst that can happen is that they wait for
- // MOZ_XREMOTE_START_TIMEOUT_SEC during startup in that case.
- if (username) {
- mutexPath.Append(username);
- }
- if (profile) {
- mutexPath.Append(NS_LITERAL_CSTRING("_") + nsDependentCString(profile));
- }
- mutexDir->AppendNative(mutexPath);
- rv = mutexDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
- if (NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_ALREADY_EXISTS) {
- mRemoteLockDir = mutexDir;
- }
- }
- if (mRemoteLockDir) {
- const TimeStamp epoch = mozilla::TimeStamp::Now();
- do {
- rv = mRemoteLock.Lock(mRemoteLockDir, nullptr);
- if (NS_SUCCEEDED(rv))
- break;
- sched_yield();
- } while ((TimeStamp::Now() - epoch)
- < TimeDuration::FromSeconds(MOZ_XREMOTE_START_TIMEOUT_SEC));
- if (NS_FAILED(rv)) {
- NS_WARNING("Cannot lock XRemote start mutex");
- }
- }
- // Try to remote the entire command line. If this fails, start up normally.
- const char* desktopStartupIDPtr =
- mDesktopStartupID.IsEmpty() ? nullptr : mDesktopStartupID.get();
- rr = StartRemoteClient(desktopStartupIDPtr, program, profile, username);
- if (rr == REMOTE_FOUND) {
- *aExitFlag = true;
- return 0;
- } else if (rr == REMOTE_ARG_BAD) {
- return 1;
- }
- }
- #endif
- #if defined(MOZ_WIDGET_GTK)
- g_set_application_name(mAppData->name);
- gtk_window_set_auto_startup_notification(false);
- #if (MOZ_WIDGET_GTK == 2)
- gtk_widget_set_default_colormap(gdk_rgb_get_colormap());
- #endif /* (MOZ_WIDGET_GTK == 2) */
- #endif /* defined(MOZ_WIDGET_GTK) */
- #ifdef MOZ_X11
- // Do this after initializing GDK, or GDK will install its own handler.
- XRE_InstallX11ErrorHandler();
- #endif
- rv = NS_CreateNativeAppSupport(getter_AddRefs(mNativeApp));
- if (NS_FAILED(rv))
- return 1;
- bool canRun = false;
- rv = mNativeApp->Start(&canRun);
- if (NS_FAILED(rv) || !canRun) {
- return 1;
- }
- #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
- // DESKTOP_STARTUP_ID is cleared now,
- // we recover it in case we need a restart.
- if (!mDesktopStartupID.IsEmpty()) {
- nsAutoCString desktopStartupEnv;
- desktopStartupEnv.AssignLiteral("DESKTOP_STARTUP_ID=");
- desktopStartupEnv.Append(mDesktopStartupID);
- // Leak it with extreme prejudice!
- PR_SetEnv(ToNewCString(desktopStartupEnv));
- }
- #endif
- #ifdef MOZ_UPDATER
- // Check for and process any available updates
- nsCOMPtr<nsIFile> updRoot;
- bool persistent;
- rv = mDirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
- getter_AddRefs(updRoot));
- // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
- if (NS_FAILED(rv))
- updRoot = mDirProvider.GetAppDir();
- // If the MOZ_TEST_PROCESS_UPDATES environment variable already exists, then
- // we are being called from the callback application.
- if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
- // If the caller has asked us to log our arguments, do so. This is used
- // to make sure that the maintenance service successfully launches the
- // callback application.
- const char *logFile = nullptr;
- if (ARG_FOUND == CheckArg("dump-args", false, &logFile)) {
- FILE* logFP = fopen(logFile, "wb");
- if (logFP) {
- for (int i = 1; i < gRestartArgc; ++i) {
- fprintf(logFP, "%s\n", gRestartArgv[i]);
- }
- fclose(logFP);
- }
- }
- *aExitFlag = true;
- return 0;
- }
- // Support for processing an update and exiting. The MOZ_TEST_PROCESS_UPDATES
- // environment variable will be part of the updater's environment and the
- // application that is relaunched by the updater. When the application is
- // relaunched by the updater it will be removed below and the application
- // will exit.
- if (CheckArg("test-process-updates")) {
- SaveToEnv("MOZ_TEST_PROCESS_UPDATES=1");
- }
- nsCOMPtr<nsIFile> exeFile, exeDir;
- rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE, &persistent,
- getter_AddRefs(exeFile));
- NS_ENSURE_SUCCESS(rv, 1);
- rv = exeFile->GetParent(getter_AddRefs(exeDir));
- NS_ENSURE_SUCCESS(rv, 1);
- ProcessUpdates(mDirProvider.GetGREDir(),
- exeDir,
- updRoot,
- gRestartArgc,
- gRestartArgv,
- mAppData->version);
- if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
- SaveToEnv("MOZ_TEST_PROCESS_UPDATES=");
- *aExitFlag = true;
- return 0;
- }
- #endif
- rv = NS_NewToolkitProfileService(getter_AddRefs(mProfileSvc));
- if (rv == NS_ERROR_FILE_ACCESS_DENIED) {
- PR_fprintf(PR_STDERR, "Error: Access was denied while trying to open files in " \
- "your profile directory.\n");
- }
- if (NS_FAILED(rv)) {
- // We failed to choose or create profile - notify user and quit
- ProfileMissingDialog(mNativeApp);
- return 1;
- }
- rv = SelectProfile(getter_AddRefs(mProfileLock), mProfileSvc, mNativeApp, &mStartOffline,
- &mProfileName);
- if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
- rv == NS_ERROR_ABORT) {
- *aExitFlag = true;
- return 0;
- }
- if (NS_FAILED(rv)) {
- // We failed to choose or create profile - notify user and quit
- ProfileMissingDialog(mNativeApp);
- return 1;
- }
- gProfileLock = mProfileLock;
- rv = mProfileLock->GetDirectory(getter_AddRefs(mProfD));
- NS_ENSURE_SUCCESS(rv, 1);
- rv = mProfileLock->GetLocalDirectory(getter_AddRefs(mProfLD));
- NS_ENSURE_SUCCESS(rv, 1);
- rv = mDirProvider.SetProfile(mProfD, mProfLD);
- NS_ENSURE_SUCCESS(rv, 1);
- //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
- mozilla::Telemetry::SetProfileDir(mProfD);
- nsAutoCString version;
- BuildVersion(version);
- #ifdef TARGET_OS_ABI
- NS_NAMED_LITERAL_CSTRING(osABI, TARGET_OS_ABI);
- #else
- // No TARGET_XPCOM_ABI, but at least the OS is known
- NS_NAMED_LITERAL_CSTRING(osABI, OS_TARGET "_UNKNOWN");
- #endif
- // Check for version compatibility with the last version of the app this
- // profile was started with. The format of the version stamp is defined
- // by the BuildVersion function.
- // Also check to see if something has happened to invalidate our
- // fastload caches, like an extension upgrade or installation.
- // If we see .purgecaches, that means someone did a make.
- // Re-register components to catch potential changes.
- nsCOMPtr<nsIFile> flagFile;
- rv = NS_ERROR_FILE_NOT_FOUND;
- nsCOMPtr<nsIFile> fFlagFile;
- if (mAppData->directory) {
- rv = mAppData->directory->Clone(getter_AddRefs(fFlagFile));
- }
- flagFile = do_QueryInterface(fFlagFile);
- if (flagFile) {
- flagFile->AppendNative(FILE_INVALIDATE_CACHES);
- }
- bool cachesOK;
- bool versionOK = CheckCompatibility(mProfD, version, osABI,
- mDirProvider.GetGREDir(),
- mAppData->directory, flagFile,
- &cachesOK);
- if (CheckArg("purgecaches")) {
- cachesOK = false;
- }
- if (PR_GetEnv("MOZ_PURGE_CACHES")) {
- cachesOK = false;
- }
- // Every time a profile is loaded by a build with a different version,
- // it updates the compatibility.ini file saying what version last wrote
- // the fastload caches. On subsequent launches if the version matches,
- // there is no need for re-registration. If the user loads the same
- // profile in different builds the component registry must be
- // re-generated to prevent mysterious component loading failures.
- //
- bool startupCacheValid = true;
- if (gSafeMode) {
- startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
- WriteVersion(mProfD, NS_LITERAL_CSTRING("Safe Mode"), osABI,
- mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
- }
- else if (versionOK) {
- if (!cachesOK) {
- // Remove caches, forcing component re-registration.
- // The new list of additional components directories is derived from
- // information in "extensions.ini".
- startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
- // Rewrite compatibility.ini to remove the flag
- WriteVersion(mProfD, version, osABI,
- mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
- }
- // Nothing need be done for the normal startup case.
- }
- else {
- // Remove caches, forcing component re-registration
- // with the default set of components (this disables any potentially
- // troublesome incompatible XPCOM components).
- startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, true);
- // Write out version
- WriteVersion(mProfD, version, osABI,
- mDirProvider.GetGREDir(), mAppData->directory, !startupCacheValid);
- }
- if (!startupCacheValid)
- StartupCache::IgnoreDiskCache();
- if (flagFile) {
- flagFile->Remove(true);
- }
- return 0;
- }
- /*
- * XRE_mainRun - Command line startup, profile migration, and
- * the calling of appStartup->Run().
- */
- nsresult
- XREMain::XRE_mainRun()
- {
- nsresult rv = NS_OK;
- NS_ASSERTION(mScopedXPCOM, "Scoped xpcom not initialized.");
- #ifdef NS_FUNCTION_TIMER
- // initialize some common services, so we don't pay the cost for these at odd times later on;
- // SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs
- {
- nsCOMPtr<nsISupports> comp;
- comp = do_GetService("@mozilla.org/preferences-service;1");
- comp = do_GetService("@mozilla.org/network/socket-transport-service;1");
- comp = do_GetService("@mozilla.org/network/dns-service;1");
- comp = do_GetService("@mozilla.org/network/io-service;1");
- comp = do_GetService("@mozilla.org/chrome/chrome-registry;1");
- comp = do_GetService("@mozilla.org/focus-event-suppressor-service;1");
- }
- #endif
- rv = mScopedXPCOM->SetWindowCreator(mNativeApp);
- NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
- if (mStartOffline) {
- nsCOMPtr<nsIIOService2> io (do_GetService("@mozilla.org/network/io-service;1"));
- NS_ENSURE_TRUE(io, NS_ERROR_FAILURE);
- io->SetManageOfflineStatus(false);
- io->SetOffline(true);
- }
- {
- nsCOMPtr<nsIObserver> startupNotifier
- (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
- NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
- startupNotifier->Observe(nullptr, APPSTARTUP_TOPIC, nullptr);
- }
- nsCOMPtr<nsIAppStartup> appStartup
- (do_GetService(NS_APPSTARTUP_CONTRACTID));
- NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
- if (gDoMigration) {
- nsCOMPtr<nsIFile> file;
- mDirProvider.GetAppDir()->Clone(getter_AddRefs(file));
- file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
- nsINIParser parser;
- nsresult rv = parser.Init(file);
- // if override.ini doesn't exist, also check for distribution.ini
- if (NS_FAILED(rv)) {
- bool persistent;
- mDirProvider.GetFile(XRE_APP_DISTRIBUTION_DIR, &persistent,
- getter_AddRefs(file));
- file->AppendNative(NS_LITERAL_CSTRING("distribution.ini"));
- rv = parser.Init(file);
- }
- if (NS_SUCCEEDED(rv)) {
- nsAutoCString buf;
- rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
- if (NS_SUCCEEDED(rv)) {
- if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
- gDoMigration = false;
- }
- }
- }
- }
- {
- nsCOMPtr<nsIToolkitProfile> profileBeingReset;
- bool profileWasSelected = false;
- if (gDoProfileReset) {
- if (gResetOldProfileName.IsEmpty()) {
- NS_WARNING("Not resetting profile as the profile has no name.");
- gDoProfileReset = false;
- } else {
- rv = mProfileSvc->GetProfileByName(gResetOldProfileName,
- getter_AddRefs(profileBeingReset));
- if (NS_FAILED(rv)) {
- gDoProfileReset = false;
- return NS_ERROR_FAILURE;
- }
- nsCOMPtr<nsIToolkitProfile> defaultProfile;
- // This can fail if there is no default profile.
- // That shouldn't stop reset from proceeding.
- nsresult gotSelected = mProfileSvc->GetSelectedProfile(getter_AddRefs(defaultProfile));
- if (NS_SUCCEEDED(gotSelected)) {
- profileWasSelected = defaultProfile == profileBeingReset;
- }
- }
- }
- // Profile Migration
- if (mAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
- gDoMigration = false;
- nsCOMPtr<nsIProfileMigrator> pm(do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
- if (pm) {
- nsAutoCString aKey;
- if (gDoProfileReset) {
- // Automatically migrate from the current application if we just
- // reset the profile.
- // For Basilisk and Pale Moon:
- // Hard-code MOZ_APP_NAME to firefox because of hard-coded type in migrator.
- aKey = (((MOZ_APP_NAME == "basilisk")
- || (MOZ_APP_NAME == "palemoon"))
- ? "firefox" : MOZ_APP_NAME);
- }
- pm->Migrate(&mDirProvider, aKey, gResetOldProfileName);
- }
- }
- if (gDoProfileReset) {
- nsresult backupCreated = ProfileResetCleanup(profileBeingReset);
- if (NS_FAILED(backupCreated)) NS_WARNING("Could not cleanup the profile that was reset");
- nsCOMPtr<nsIToolkitProfile> newProfile;
- rv = GetCurrentProfile(mProfileSvc, mProfD, getter_AddRefs(newProfile));
- if (NS_SUCCEEDED(rv)) {
- newProfile->SetName(gResetOldProfileName);
- mProfileName.Assign(gResetOldProfileName);
- // Set the new profile as the default after we're done cleaning up the old profile,
- // iff that profile was already the default
- if (profileWasSelected) {
- rv = mProfileSvc->SetDefaultProfile(newProfile);
- if (NS_FAILED(rv)) NS_WARNING("Could not set current profile as the default");
- }
- } else {
- NS_WARNING("Could not find current profile to set as default / change name.");
- }
- // Need to write out the fact that the profile has been removed, the new profile
- // renamed, and potentially that the selected/default profile changed.
- mProfileSvc->Flush();
- }
- }
- mDirProvider.DoStartup();
- // As FilePreferences need the profile directory, we must initialize right here.
- mozilla::FilePreferences::InitDirectoriesWhitelist();
- mozilla::FilePreferences::InitPrefs();
- OverrideDefaultLocaleIfNeeded();
- appStartup->GetShuttingDown(&mShuttingDown);
- nsCOMPtr<nsICommandLineRunner> cmdLine;
- nsCOMPtr<nsIFile> workingDir;
- rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
- NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
- if (!mShuttingDown) {
- cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
- NS_ENSURE_TRUE(cmdLine, NS_ERROR_FAILURE);
- rv = cmdLine->Init(gArgc, gArgv, workingDir,
- nsICommandLine::STATE_INITIAL_LAUNCH);
- NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
- /* Special-case services that need early access to the command
- line. */
- nsCOMPtr<nsIObserverService> obsService =
- mozilla::services::GetObserverService();
- if (obsService) {
- obsService->NotifyObservers(cmdLine, "command-line-startup", nullptr);
- }
- }
- #ifdef XP_WIN
- // Hack to sync up the various environment storages. XUL_APP_FILE is special
- // in that it comes from a different CRT (firefox.exe's static-linked copy).
- // Ugly details in http://bugzil.la/1175039#c27
- char appFile[MAX_PATH];
- if (GetEnvironmentVariableA("XUL_APP_FILE", appFile, sizeof(appFile))) {
- char* saved = PR_smprintf("XUL_APP_FILE=%s", appFile);
- PR_SetEnv(saved);
- PR_smprintf_free(saved);
- }
- #endif
- SaveStateForAppInitiatedRestart();
- // clear out any environment variables which may have been set
- // during the relaunch process now that we know we won't be relaunching.
- SaveToEnv("XRE_PROFILE_PATH=");
- SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
- SaveToEnv("XRE_PROFILE_NAME=");
- SaveToEnv("XRE_START_OFFLINE=");
- SaveToEnv("NO_EM_RESTART=");
- SaveToEnv("XUL_APP_FILE=");
- SaveToEnv("XRE_BINARY_PATH=");
- if (!mShuttingDown) {
- rv = appStartup->CreateHiddenWindow();
- NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
- #ifdef MOZ_STYLO
- // We initialize Servo here so that the hidden DOM window is available,
- // since initializing Servo calls style struct constructors, and the
- // HackilyFindDeviceContext stuff we have right now depends on the hidden
- // DOM window. When we fix that, this should move back to
- // nsLayoutStatics.cpp
- Servo_Initialize();
- #endif
- #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
- nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
- if (toolkit && !mDesktopStartupID.IsEmpty()) {
- toolkit->SetDesktopStartupID(mDesktopStartupID);
- }
- // Clear the environment variable so it won't be inherited by
- // child processes and confuse things.
- g_unsetenv ("DESKTOP_STARTUP_ID");
- #endif
- nsCOMPtr<nsIObserverService> obsService =
- mozilla::services::GetObserverService();
- if (obsService)
- obsService->NotifyObservers(nullptr, "final-ui-startup", nullptr);
- (void)appStartup->DoneStartingUp();
- appStartup->GetShuttingDown(&mShuttingDown);
- }
- if (!mShuttingDown) {
- rv = cmdLine->Run();
- NS_ENSURE_SUCCESS_LOG(rv, NS_ERROR_FAILURE);
- appStartup->GetShuttingDown(&mShuttingDown);
- }
- if (!mShuttingDown) {
- #ifdef MOZ_ENABLE_XREMOTE
- // if we have X remote support, start listening for requests on the
- // proxy window.
- if (!mDisableRemote)
- mRemoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
- if (mRemoteService)
- mRemoteService->Startup(mAppData->remotingName, mProfileName.get());
- if (mRemoteLockDir) {
- mRemoteLock.Unlock();
- mRemoteLockDir->Remove(false);
- }
- #endif /* MOZ_ENABLE_XREMOTE */
- mNativeApp->Enable();
- }
- #ifdef MOZ_INSTRUMENT_EVENT_LOOP
- if (PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP")) {
- bool logToConsole = true;
- mozilla::InitEventTracing(logToConsole);
- }
- #endif /* MOZ_INSTRUMENT_EVENT_LOOP */
- {
- rv = appStartup->Run();
- if (NS_FAILED(rv)) {
- NS_ERROR("failed to run appstartup");
- gLogConsoleErrors = true;
- }
- }
- #ifdef MOZ_STYLO
- // This, along with the call to Servo_Initialize, should eventually move back
- // to nsLayoutStatics.cpp.
- Servo_Shutdown();
- #endif
- return rv;
- }
- #if MOZ_WIDGET_GTK == 2
- void XRE_GlibInit()
- {
- static bool ran_once = false;
- // glib < 2.24 doesn't want g_thread_init to be invoked twice, so ensure
- // we only do it once. No need for thread safety here, since this is invoked
- // well before any thread is spawned.
- if (!ran_once) {
- // glib version < 2.36 doesn't initialize g_slice in a static initializer.
- // Ensure this happens through g_thread_init (glib version < 2.32) or
- // g_type_init (2.32 <= gLib version < 2.36)."
- g_thread_init(nullptr);
- g_type_init();
- ran_once = true;
- }
- }
- #endif
- // Separate stub function to let us specifically suppress it in Valgrind
- void
- XRE_CreateStatsObject()
- {
- // Initialize global variables used by histogram collection
- // machinery that is used by by Telemetry. Note: is never de-initialised.
- Telemetry::CreateStatisticsRecorder();
- }
- /*
- * XRE_main - A class based main entry point used by most platforms.
- * Note that on OSX, aAppData->xreDirectory will point to
- * .app/Contents/Resources.
- */
- int
- XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
- {
- ScopedLogging log;
- // NB: this must happen after the creation of |ScopedLogging log| since
- // ScopedLogging::ScopedLogging calls NS_LogInit, and
- // XRE_CreateStatsObject calls Telemetry::CreateStatisticsRecorder,
- // and NS_LogInit must be called before Telemetry::CreateStatisticsRecorder.
- // NS_LogInit must be called before Telemetry::CreateStatisticsRecorder
- // so as to avoid many log messages of the form
- // WARNING: XPCOM objects created/destroyed from static ctor/dtor: [..]
- // See bug 1279614.
- XRE_CreateStatsObject();
- char aLocal;
- GeckoProfilerInitRAII profilerGuard(&aLocal);
- PROFILER_LABEL("Startup", "XRE_Main",
- js::ProfileEntry::Category::OTHER);
- nsresult rv = NS_OK;
- gArgc = argc;
- gArgv = argv;
- NS_ENSURE_TRUE(aAppData, 2);
- mAppData = new ScopedAppData(aAppData);
- if (!mAppData)
- return 1;
- if (!mAppData->remotingName) {
- SetAllocatedString(mAppData->remotingName, mAppData->name);
- }
- // used throughout this file
- gAppData = mAppData;
- nsCOMPtr<nsIFile> binFile;
- rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(binFile));
- NS_ENSURE_SUCCESS(rv, 1);
- rv = binFile->GetPath(gAbsoluteArgv0Path);
- NS_ENSURE_SUCCESS(rv, 1);
- mozilla::IOInterposerInit ioInterposerGuard;
- #if defined(XP_WIN)
- // Some COM settings are global to the process and must be set before any non-
- // trivial COM is run in the application. Since these settings may affect
- // stability, we should instantiate COM ASAP so that we can ensure that these
- // global settings are configured before anything can interfere.
- mozilla::mscom::MainThreadRuntime msCOMRuntime;
- #endif
- #if MOZ_WIDGET_GTK == 2
- XRE_GlibInit();
- #endif
- // init
- bool exit = false;
- int result = XRE_mainInit(&exit);
- if (result != 0 || exit)
- return result;
- // startup
- result = XRE_mainStartup(&exit);
- if (result != 0 || exit)
- return result;
- bool appInitiatedRestart = false;
- // Start the real application
- mScopedXPCOM = MakeUnique<ScopedXPCOMStartup>();
- if (!mScopedXPCOM)
- return 1;
- rv = mScopedXPCOM->Initialize();
- NS_ENSURE_SUCCESS(rv, 1);
- // run!
- rv = XRE_mainRun();
- #ifdef MOZ_INSTRUMENT_EVENT_LOOP
- mozilla::ShutdownEventTracing();
- #endif
- gAbsoluteArgv0Path.Truncate();
- // Check for an application initiated restart. This is one that
- // corresponds to nsIAppStartup.quit(eRestart)
- if (rv == NS_SUCCESS_RESTART_APP
- || rv == NS_SUCCESS_RESTART_APP_NOT_SAME_PROFILE) {
- appInitiatedRestart = true;
- // We have an application restart don't do any shutdown checks here
- // In particular we don't want to poison IO for checking late-writes.
- gShutdownChecks = SCM_NOTHING;
- }
- if (!mShuttingDown) {
- #ifdef MOZ_ENABLE_XREMOTE
- // shut down the x remote proxy window
- if (mRemoteService) {
- mRemoteService->Shutdown();
- }
- #endif /* MOZ_ENABLE_XREMOTE */
- }
- mScopedXPCOM = nullptr;
- #if defined(XP_WIN)
- mozilla::widget::StopAudioSession();
- #endif
- // unlock the profile after ScopedXPCOMStartup object (xpcom)
- // has gone out of scope. see bug #386739 for more details
- mProfileLock->Unlock();
- gProfileLock = nullptr;
- // Restart the app after XPCOM has been shut down cleanly.
- if (appInitiatedRestart) {
- RestoreStateForAppInitiatedRestart();
- if (rv != NS_SUCCESS_RESTART_APP_NOT_SAME_PROFILE) {
- // Ensure that these environment variables are set:
- SaveFileToEnvIfUnset("XRE_PROFILE_PATH", mProfD);
- SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", mProfLD);
- SaveWordToEnvIfUnset("XRE_PROFILE_NAME", mProfileName);
- }
- #ifdef MOZ_WIDGET_GTK
- MOZ_gdk_display_close(mGdkDisplay);
- #endif
- {
- rv = LaunchChild(mNativeApp, true);
- }
- return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
- }
- #ifdef MOZ_WIDGET_GTK
- // gdk_display_close also calls gdk_display_manager_set_default_display
- // appropriately when necessary.
- MOZ_gdk_display_close(mGdkDisplay);
- #endif
- XRE_DeinitCommandLine();
- return NS_FAILED(rv) ? 1 : 0;
- }
- void
- XRE_StopLateWriteChecks(void) {
- mozilla::StopLateWriteChecks();
- }
- int
- XRE_main(int argc, char* argv[], const nsXREAppData* aAppData, uint32_t aFlags)
- {
- XREMain main;
- int result = main.XRE_main(argc, argv, aAppData);
- mozilla::RecordShutdownEndTimeStamp();
- return result;
- }
- nsresult
- XRE_InitCommandLine(int aArgc, char* aArgv[])
- {
- nsresult rv = NS_OK;
- #if defined(OS_WIN)
- CommandLine::Init(aArgc, aArgv);
- #else
- // these leak on error, but that's OK: we'll just exit()
- char** canonArgs = new char*[aArgc];
- // get the canonical version of the binary's path
- nsCOMPtr<nsIFile> binFile;
- rv = XRE_GetBinaryPath(aArgv[0], getter_AddRefs(binFile));
- if (NS_FAILED(rv))
- return NS_ERROR_FAILURE;
- nsAutoCString canonBinPath;
- rv = binFile->GetNativePath(canonBinPath);
- if (NS_FAILED(rv))
- return NS_ERROR_FAILURE;
- canonArgs[0] = strdup(canonBinPath.get());
- for (int i = 1; i < aArgc; ++i) {
- if (aArgv[i]) {
- canonArgs[i] = strdup(aArgv[i]);
- }
- }
- NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!");
- CommandLine::Init(aArgc, canonArgs);
- for (int i = 0; i < aArgc; ++i)
- free(canonArgs[i]);
- delete[] canonArgs;
- #endif
- if (PR_GetEnv("UXP_CUSTOM_OMNI")) {
- // Process CLI parameters for specifying custom omnijars
- const char *path = nullptr;
- ArgResult ar = CheckArg("greomni", true, &path);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR,
- "Error: argument --greomni requires a path argument or the "
- "--osint argument was specified with the --greomni argument "
- "which is invalid.\n");
- return NS_ERROR_FAILURE;
- }
- if (!path)
- return rv;
- nsCOMPtr<nsIFile> greOmni;
- rv = XRE_GetFileFromPath(path, getter_AddRefs(greOmni));
- if (NS_FAILED(rv)) {
- PR_fprintf(PR_STDERR, "Error: argument --greomni requires a valid path\n");
- return rv;
- }
- ar = CheckArg("appomni", true, &path);
- if (ar == ARG_BAD) {
- PR_fprintf(PR_STDERR,
- "Error: argument --appomni requires a path argument or the "
- "--osint argument was specified with the --appomni argument "
- "which is invalid.\n");
- return NS_ERROR_FAILURE;
- }
- nsCOMPtr<nsIFile> appOmni;
- if (path) {
- rv = XRE_GetFileFromPath(path, getter_AddRefs(appOmni));
- if (NS_FAILED(rv)) {
- PR_fprintf(PR_STDERR, "Error: argument --appomni requires a valid path\n");
- return rv;
- }
- }
- mozilla::Omnijar::Init(greOmni, appOmni);
- } // UXP_CUSTOM_OMNI
- return rv;
- }
- nsresult
- XRE_DeinitCommandLine()
- {
- nsresult rv = NS_OK;
- CommandLine::Terminate();
- return rv;
- }
- GeckoProcessType
- XRE_GetProcessType()
- {
- return mozilla::startup::sChildProcessType;
- }
- bool
- XRE_IsGPUProcess()
- {
- return XRE_GetProcessType() == GeckoProcessType_GPU;
- }
- bool
- XRE_IsParentProcess()
- {
- return XRE_GetProcessType() == GeckoProcessType_Default;
- }
- bool
- XRE_IsContentProcess()
- {
- return XRE_GetProcessType() == GeckoProcessType_Content;
- }
- // If you add anything to this enum, please update about:support to reflect it
- enum {
- kE10sEnabledByUser = 0,
- kE10sEnabledByDefault = 1,
- kE10sDisabledByUser = 2,
- // kE10sDisabledInSafeMode = 3, was removed in bug 1172491.
- kE10sDisabledForAccessibility = 4,
- // kE10sDisabledForMacGfx = 5, was removed in bug 1068674.
- // kE10sDisabledForBidi = 6, removed in bug 1309599
- kE10sDisabledForAddons = 7,
- kE10sForceDisabled = 8,
- // kE10sDisabledForXPAcceleration = 9, removed in bug 1296353
- // kE10sDisabledForOperatingSystem = 10, removed due to xp-eol
- };
- const char* kAccessibilityLastRunDatePref = "accessibility.lastLoadDate";
- const char* kAccessibilityLoadedLastSessionPref = "accessibility.loadedInLastSession";
- #if defined(XP_WIN)
- static inline uint32_t
- PRTimeToSeconds(PRTime t_usec)
- {
- PRTime usec_per_sec = PR_USEC_PER_SEC;
- return uint32_t(t_usec /= usec_per_sec);
- }
- #endif
- uint32_t
- MultiprocessBlockPolicy() {
- if (gMultiprocessBlockPolicyInitialized) {
- return gMultiprocessBlockPolicy;
- }
- gMultiprocessBlockPolicyInitialized = true;
- // We do not support E10S, block by policy.
- gMultiprocessBlockPolicy = kE10sForceDisabled;
- return gMultiprocessBlockPolicy;
- }
- bool
- mozilla::BrowserTabsRemoteAutostart()
- {
- if (gBrowserTabsRemoteAutostartInitialized) {
- return gBrowserTabsRemoteAutostart;
- }
- gBrowserTabsRemoteAutostartInitialized = true;
- bool optInPref = Preferences::GetBool("browser.tabs.remote.autostart", false);
- bool trialPref = Preferences::GetBool("browser.tabs.remote.autostart.2", false);
- bool prefEnabled = optInPref || trialPref;
- int status;
- if (prefEnabled) {
- uint32_t blockPolicy = MultiprocessBlockPolicy();
- if (blockPolicy != 0) {
- status = blockPolicy;
- } else {
- MOZ_CRASH("e10s force enabled bypassing policy -- unsupported configuration");
- }
- } else {
- status = kE10sDisabledByUser;
- }
- gBrowserTabsRemoteStatus = status;
- return gBrowserTabsRemoteAutostart;
- }
- void
- SetupErrorHandling(const char* progname)
- {
- #ifdef XP_WIN
- /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
- we still want DEP protection: enable it explicitly and programmatically.
- This function is not available on WinXPSP2 so we dynamically load it.
- */
- HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
- SetProcessDEPPolicyFunc _SetProcessDEPPolicy =
- (SetProcessDEPPolicyFunc) GetProcAddress(kernel32, "SetProcessDEPPolicy");
- if (_SetProcessDEPPolicy)
- _SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
- #endif
- #ifdef XP_WIN32
- // Suppress the "DLL Foo could not be found" dialog, such that if dependent
- // libraries (such as GDI+) are not preset, we gracefully fail to load those
- // XPCOM components, instead of being ungraceful.
- UINT realMode = SetErrorMode(0);
- realMode |= SEM_FAILCRITICALERRORS;
- // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
- // application has crashed" dialog box. This is mainly useful for
- // automated testing environments, e.g. tinderbox, where there's no need
- // for a dozen of the dialog boxes to litter the console
- if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
- realMode |= SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
- SetErrorMode(realMode);
- #endif
- #if defined (DEBUG) && defined(XP_WIN)
- // Send MSCRT Warnings, Errors and Assertions to stderr.
- // See http://msdn.microsoft.com/en-us/library/1y71x448(v=VS.80).aspx
- // and http://msdn.microsoft.com/en-us/library/a68f826y(v=VS.80).aspx.
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
- _CrtSetReportHook(MSCRTReportHook);
- #endif
- InstallSignalHandlers(progname);
- // Unbuffer stdout, needed for tinderbox tests.
- setbuf(stdout, 0);
- }
- void
- OverrideDefaultLocaleIfNeeded() {
- // Read pref to decide whether to override default locale with US English.
- if (mozilla::Preferences::GetBool("javascript.use_us_english_locale", false)) {
- // Set the application-wide C-locale. Needed to resist fingerprinting
- // of Date.toLocaleFormat(). We use the locale to "C.UTF-8" if possible,
- // to avoid interfering with non-ASCII keyboard input on some Linux desktops.
- // Otherwise fall back to the "C" locale, which is available on all platforms.
- setlocale(LC_ALL, "C.UTF-8") || setlocale(LC_ALL, "C");
- }
- }
- void
- XRE_EnableSameExecutableForContentProc() {
- if (!PR_GetEnv("MOZ_SEPARATE_CHILD_PROCESS")) {
- mozilla::ipc::GeckoChildProcessHost::EnableSameExecutableForContentProc();
- }
- }
|