nsXREDirProvider.cpp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "nsAppRunner.h"
  6. #include "nsToolkitCompsCID.h"
  7. #include "nsXREDirProvider.h"
  8. #include "jsapi.h"
  9. #include "xpcpublic.h"
  10. #include "nsIAddonInterposition.h"
  11. #include "nsIAppStartup.h"
  12. #include "nsIDirectoryEnumerator.h"
  13. #include "nsIFile.h"
  14. #include "nsIObserver.h"
  15. #include "nsIObserverService.h"
  16. #include "nsISimpleEnumerator.h"
  17. #include "nsIToolkitChromeRegistry.h"
  18. #include "nsIToolkitProfileService.h"
  19. #include "nsIXULRuntime.h"
  20. #include "nsAppDirectoryServiceDefs.h"
  21. #include "nsDirectoryServiceDefs.h"
  22. #include "nsDirectoryServiceUtils.h"
  23. #include "nsXULAppAPI.h"
  24. #include "nsCategoryManagerUtils.h"
  25. #include "nsINIParser.h"
  26. #include "nsDependentString.h"
  27. #include "nsCOMArray.h"
  28. #include "nsArrayEnumerator.h"
  29. #include "nsEnumeratorUtils.h"
  30. #include "nsReadableUtils.h"
  31. #include "SpecialSystemDirectory.h"
  32. #include "mozilla/dom/ScriptSettings.h"
  33. #include "mozilla/Services.h"
  34. #include "mozilla/Omnijar.h"
  35. #include "mozilla/Preferences.h"
  36. #include "mozilla/Telemetry.h"
  37. #include <stdlib.h>
  38. #ifdef XP_WIN
  39. #include <windows.h>
  40. #include <shlobj.h>
  41. #endif
  42. #ifdef XP_UNIX
  43. #include <ctype.h>
  44. #endif
  45. #if defined(XP_WIN)
  46. #define APP_REGISTRY_NAME "registry.dat"
  47. #else
  48. #define APP_REGISTRY_NAME "appreg"
  49. #endif
  50. #define PREF_OVERRIDE_DIRNAME "preferences"
  51. static already_AddRefed<nsIFile>
  52. CloneAndAppend(nsIFile* aFile, const char* name)
  53. {
  54. nsCOMPtr<nsIFile> file;
  55. aFile->Clone(getter_AddRefs(file));
  56. file->AppendNative(nsDependentCString(name));
  57. return file.forget();
  58. }
  59. nsXREDirProvider* gDirServiceProvider = nullptr;
  60. nsXREDirProvider::nsXREDirProvider() :
  61. mProfileNotified(false)
  62. {
  63. gDirServiceProvider = this;
  64. }
  65. nsXREDirProvider::~nsXREDirProvider()
  66. {
  67. gDirServiceProvider = nullptr;
  68. }
  69. nsXREDirProvider*
  70. nsXREDirProvider::GetSingleton()
  71. {
  72. return gDirServiceProvider;
  73. }
  74. nsresult
  75. nsXREDirProvider::Initialize(nsIFile *aXULAppDir,
  76. nsIFile *aGREDir,
  77. nsIDirectoryServiceProvider* aAppProvider)
  78. {
  79. NS_ENSURE_ARG(aXULAppDir);
  80. NS_ENSURE_ARG(aGREDir);
  81. mAppProvider = aAppProvider;
  82. mXULAppDir = aXULAppDir;
  83. mGREDir = aGREDir;
  84. mGREDir->Clone(getter_AddRefs(mGREBinDir));
  85. if (!mProfileDir) {
  86. nsCOMPtr<nsIDirectoryServiceProvider> app(do_QueryInterface(mAppProvider));
  87. if (app) {
  88. bool per = false;
  89. app->GetFile(NS_APP_USER_PROFILE_50_DIR, &per, getter_AddRefs(mProfileDir));
  90. NS_ASSERTION(per, "NS_APP_USER_PROFILE_50_DIR must be persistent!");
  91. NS_ASSERTION(mProfileDir, "NS_APP_USER_PROFILE_50_DIR not defined! This shouldn't happen!");
  92. }
  93. }
  94. return NS_OK;
  95. }
  96. nsresult
  97. nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir)
  98. {
  99. NS_ASSERTION(aDir && aLocalDir, "We don't support no-profile apps yet!");
  100. nsresult rv;
  101. rv = EnsureDirectoryExists(aDir);
  102. if (NS_FAILED(rv))
  103. return rv;
  104. rv = EnsureDirectoryExists(aLocalDir);
  105. if (NS_FAILED(rv))
  106. return rv;
  107. mProfileDir = aDir;
  108. mProfileLocalDir = aLocalDir;
  109. return NS_OK;
  110. }
  111. NS_IMPL_QUERY_INTERFACE(nsXREDirProvider,
  112. nsIDirectoryServiceProvider,
  113. nsIDirectoryServiceProvider2,
  114. nsIProfileStartup)
  115. NS_IMETHODIMP_(MozExternalRefCountType)
  116. nsXREDirProvider::AddRef()
  117. {
  118. return 1;
  119. }
  120. NS_IMETHODIMP_(MozExternalRefCountType)
  121. nsXREDirProvider::Release()
  122. {
  123. return 0;
  124. }
  125. nsresult
  126. nsXREDirProvider::GetUserProfilesRootDir(nsIFile** aResult,
  127. const nsACString* aProfileName,
  128. const nsACString* aAppName,
  129. const nsACString* aVendorName)
  130. {
  131. nsCOMPtr<nsIFile> file;
  132. nsresult rv = GetUserDataDirectory(getter_AddRefs(file),
  133. false,
  134. aProfileName, aAppName, aVendorName);
  135. if (NS_SUCCEEDED(rv)) {
  136. #if !defined(XP_UNIX)
  137. rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
  138. #endif
  139. // We must create the profile directory here if it does not exist.
  140. nsresult tmp = EnsureDirectoryExists(file);
  141. if (NS_FAILED(tmp)) {
  142. rv = tmp;
  143. }
  144. }
  145. file.swap(*aResult);
  146. return rv;
  147. }
  148. nsresult
  149. nsXREDirProvider::GetUserProfilesLocalDir(nsIFile** aResult,
  150. const nsACString* aProfileName,
  151. const nsACString* aAppName,
  152. const nsACString* aVendorName)
  153. {
  154. nsCOMPtr<nsIFile> file;
  155. nsresult rv = GetUserDataDirectory(getter_AddRefs(file),
  156. true,
  157. aProfileName, aAppName, aVendorName);
  158. if (NS_SUCCEEDED(rv)) {
  159. #if !defined(XP_UNIX)
  160. rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
  161. #endif
  162. // We must create the profile directory here if it does not exist.
  163. nsresult tmp = EnsureDirectoryExists(file);
  164. if (NS_FAILED(tmp)) {
  165. rv = tmp;
  166. }
  167. }
  168. file.swap(*aResult);
  169. return NS_OK;
  170. }
  171. #if defined(XP_UNIX)
  172. /**
  173. * Get the directory that is the parent of the system-wide directories
  174. * for extensions and native-messaing manifests.
  175. *
  176. * On OSX this is /Library/Application Support/Mozilla
  177. * On Linux this is /usr/{lib,lib64}/mozilla
  178. * (for 32- and 64-bit systems respsectively)
  179. */
  180. static nsresult
  181. GetSystemParentDirectory(nsIFile** aFile)
  182. {
  183. nsresult rv;
  184. nsCOMPtr<nsIFile> localDir;
  185. NS_NAMED_LITERAL_CSTRING(dirname,
  186. #ifdef HAVE_USR_LIB64_DIR
  187. "/usr/lib64/mozilla"
  188. #elif defined(__OpenBSD__) || defined(__FreeBSD__)
  189. "/usr/local/lib/mozilla"
  190. #else
  191. "/usr/lib/mozilla"
  192. #endif
  193. );
  194. rv = NS_NewNativeLocalFile(dirname, false, getter_AddRefs(localDir));
  195. if (NS_SUCCEEDED(rv)) {
  196. localDir.forget(aFile);
  197. }
  198. return rv;
  199. }
  200. #endif
  201. NS_IMETHODIMP
  202. nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
  203. nsIFile** aFile)
  204. {
  205. nsresult rv;
  206. bool gettingProfile = false;
  207. if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) {
  208. // If XRE_NotifyProfile hasn't been called, don't fall through to
  209. // mAppProvider on the profile keys.
  210. if (!mProfileNotified)
  211. return NS_ERROR_FAILURE;
  212. if (mProfileLocalDir)
  213. return mProfileLocalDir->Clone(aFile);
  214. if (mAppProvider)
  215. return mAppProvider->GetFile(aProperty, aPersistent, aFile);
  216. // This falls through to the case below
  217. gettingProfile = true;
  218. }
  219. if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || gettingProfile) {
  220. if (!mProfileNotified)
  221. return NS_ERROR_FAILURE;
  222. if (mProfileDir)
  223. return mProfileDir->Clone(aFile);
  224. if (mAppProvider)
  225. return mAppProvider->GetFile(aProperty, aPersistent, aFile);
  226. // If we don't succeed here, bail early so that we aren't reentrant
  227. // through the "GetProfileDir" call below.
  228. return NS_ERROR_FAILURE;
  229. }
  230. if (mAppProvider) {
  231. rv = mAppProvider->GetFile(aProperty, aPersistent, aFile);
  232. if (NS_SUCCEEDED(rv) && *aFile)
  233. return rv;
  234. }
  235. *aPersistent = true;
  236. if (!strcmp(aProperty, NS_GRE_DIR)) {
  237. return mGREDir->Clone(aFile);
  238. }
  239. else if (!strcmp(aProperty, NS_GRE_BIN_DIR)) {
  240. return mGREBinDir->Clone(aFile);
  241. }
  242. else if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) ||
  243. !strcmp(aProperty, NS_APP_INSTALL_CLEANUP_DIR)) {
  244. return GetAppDir()->Clone(aFile);
  245. }
  246. rv = NS_ERROR_FAILURE;
  247. nsCOMPtr<nsIFile> file;
  248. if (!strcmp(aProperty, NS_APP_PREF_DEFAULTS_50_DIR))
  249. {
  250. // return the GRE default prefs directory here, and the app default prefs
  251. // directory (if applicable) in NS_APP_PREFS_DEFAULTS_DIR_LIST.
  252. rv = mGREDir->Clone(getter_AddRefs(file));
  253. if (NS_SUCCEEDED(rv)) {
  254. rv = file->AppendNative(NS_LITERAL_CSTRING("defaults"));
  255. if (NS_SUCCEEDED(rv))
  256. rv = file->AppendNative(NS_LITERAL_CSTRING("pref"));
  257. }
  258. }
  259. else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_DIR) ||
  260. !strcmp(aProperty, XRE_USER_APP_DATA_DIR)) {
  261. rv = GetUserAppDataDirectory(getter_AddRefs(file));
  262. }
  263. #if defined(XP_UNIX)
  264. else if (!strcmp(aProperty, XRE_SYS_NATIVE_MESSAGING_MANIFESTS)) {
  265. nsCOMPtr<nsIFile> localDir;
  266. rv = ::GetSystemParentDirectory(getter_AddRefs(localDir));
  267. if (NS_SUCCEEDED(rv)) {
  268. NS_NAMED_LITERAL_CSTRING(dirname,
  269. "native-messaging-hosts"
  270. );
  271. rv = localDir->AppendNative(dirname);
  272. if (NS_SUCCEEDED(rv)) {
  273. localDir.swap(file);
  274. }
  275. }
  276. }
  277. else if (!strcmp(aProperty, XRE_USER_NATIVE_MESSAGING_MANIFESTS)) {
  278. nsCOMPtr<nsIFile> localDir;
  279. rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
  280. if (NS_SUCCEEDED(rv)) {
  281. rv = localDir->AppendNative(NS_LITERAL_CSTRING(".mozilla"));
  282. if (NS_SUCCEEDED(rv)) {
  283. rv = localDir->AppendNative(NS_LITERAL_CSTRING("native-messaging-hosts"));
  284. }
  285. }
  286. if (NS_SUCCEEDED(rv)) {
  287. localDir.swap(file);
  288. }
  289. }
  290. #endif
  291. else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) {
  292. rv = GetUpdateRootDir(getter_AddRefs(file));
  293. }
  294. else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) {
  295. rv = GetUserAppDataDirectory(getter_AddRefs(file));
  296. if (NS_SUCCEEDED(rv))
  297. rv = file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME));
  298. }
  299. else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) {
  300. rv = GetUserProfilesRootDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
  301. }
  302. else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) {
  303. rv = GetUserProfilesLocalDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
  304. }
  305. else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) {
  306. nsCOMPtr<nsIFile> lf;
  307. rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
  308. if (NS_SUCCEEDED(rv))
  309. file = lf;
  310. }
  311. else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) {
  312. return mProfileDir->Clone(aFile);
  313. }
  314. else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
  315. if (mProfileLocalDir)
  316. return mProfileLocalDir->Clone(aFile);
  317. if (mProfileDir)
  318. return mProfileDir->Clone(aFile);
  319. if (mAppProvider)
  320. return mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, aPersistent,
  321. aFile);
  322. }
  323. #if defined(XP_UNIX)
  324. else if (!strcmp(aProperty, XRE_SYS_LOCAL_EXTENSION_PARENT_DIR)) {
  325. #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
  326. return GetSystemExtensionsDirectory(aFile);
  327. #else
  328. return NS_ERROR_FAILURE;
  329. #endif
  330. }
  331. #endif
  332. #if defined(XP_UNIX)
  333. else if (!strcmp(aProperty, XRE_SYS_SHARE_EXTENSION_PARENT_DIR)) {
  334. #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
  335. #if defined(__OpenBSD__) || defined(__FreeBSD__)
  336. static const char *const sysLExtDir = "/usr/local/share/mozilla/extensions";
  337. #else
  338. static const char *const sysLExtDir = "/usr/share/mozilla/extensions";
  339. #endif
  340. return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir),
  341. false, aFile);
  342. #else
  343. return NS_ERROR_FAILURE;
  344. #endif
  345. }
  346. #endif
  347. else if (!strcmp(aProperty, XRE_USER_SYS_EXTENSION_DIR)) {
  348. #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
  349. return GetSysUserExtensionsDirectory(aFile);
  350. #else
  351. return NS_ERROR_FAILURE;
  352. #endif
  353. }
  354. else if (!strcmp(aProperty, XRE_APP_DISTRIBUTION_DIR)) {
  355. bool persistent = false;
  356. rv = GetFile(NS_GRE_DIR, &persistent, getter_AddRefs(file));
  357. if (NS_SUCCEEDED(rv))
  358. rv = file->AppendNative(NS_LITERAL_CSTRING("distribution"));
  359. }
  360. else if (!strcmp(aProperty, XRE_APP_FEATURES_DIR)) {
  361. rv = GetAppDir()->Clone(getter_AddRefs(file));
  362. if (NS_SUCCEEDED(rv))
  363. rv = file->AppendNative(NS_LITERAL_CSTRING("features"));
  364. }
  365. else if (!strcmp(aProperty, XRE_ADDON_APP_DIR)) {
  366. nsCOMPtr<nsIDirectoryServiceProvider> dirsvc(do_GetService("@mozilla.org/file/directory_service;1", &rv));
  367. if (NS_FAILED(rv))
  368. return rv;
  369. bool unused;
  370. rv = dirsvc->GetFile("XCurProcD", &unused, getter_AddRefs(file));
  371. }
  372. else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) {
  373. // We need to allow component, xpt, and chrome registration to
  374. // occur prior to the profile-after-change notification.
  375. if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) {
  376. rv = file->AppendNative(NS_LITERAL_CSTRING("chrome"));
  377. }
  378. }
  379. if (NS_SUCCEEDED(rv) && file) {
  380. file.forget(aFile);
  381. return NS_OK;
  382. }
  383. bool ensureFilePermissions = false;
  384. if (NS_SUCCEEDED(GetProfileDir(getter_AddRefs(file)))) {
  385. if (!strcmp(aProperty, NS_APP_PREFS_50_DIR)) {
  386. rv = NS_OK;
  387. }
  388. else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) {
  389. rv = file->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
  390. }
  391. else if (!strcmp(aProperty, NS_LOCALSTORE_UNSAFE_FILE)) {
  392. rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
  393. }
  394. else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) {
  395. if (gSafeMode) {
  396. rv = file->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf"));
  397. file->Remove(false);
  398. }
  399. else {
  400. rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
  401. ensureFilePermissions = true;
  402. }
  403. }
  404. else if (!strcmp(aProperty, NS_APP_USER_MIMETYPES_50_FILE)) {
  405. rv = file->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf"));
  406. ensureFilePermissions = true;
  407. }
  408. else if (!strcmp(aProperty, NS_APP_DOWNLOADS_50_FILE)) {
  409. rv = file->AppendNative(NS_LITERAL_CSTRING("downloads.rdf"));
  410. }
  411. else if (!strcmp(aProperty, NS_APP_PREFS_OVERRIDE_DIR)) {
  412. rv = mProfileDir->Clone(getter_AddRefs(file));
  413. nsresult tmp = file->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
  414. if (NS_FAILED(tmp)) {
  415. rv = tmp;
  416. }
  417. tmp = EnsureDirectoryExists(file);
  418. if (NS_FAILED(tmp)) {
  419. rv = tmp;
  420. }
  421. }
  422. }
  423. if (NS_FAILED(rv) || !file)
  424. return NS_ERROR_FAILURE;
  425. if (ensureFilePermissions) {
  426. bool fileToEnsureExists;
  427. bool isWritable;
  428. if (NS_SUCCEEDED(file->Exists(&fileToEnsureExists)) && fileToEnsureExists
  429. && NS_SUCCEEDED(file->IsWritable(&isWritable)) && !isWritable) {
  430. uint32_t permissions;
  431. if (NS_SUCCEEDED(file->GetPermissions(&permissions))) {
  432. rv = file->SetPermissions(permissions | 0600);
  433. NS_ASSERTION(NS_SUCCEEDED(rv), "failed to ensure file permissions");
  434. }
  435. }
  436. }
  437. file.forget(aFile);
  438. return NS_OK;
  439. }
  440. static void
  441. LoadDirIntoArray(nsIFile* dir,
  442. const char *const *aAppendList,
  443. nsCOMArray<nsIFile>& aDirectories)
  444. {
  445. if (!dir)
  446. return;
  447. nsCOMPtr<nsIFile> subdir;
  448. dir->Clone(getter_AddRefs(subdir));
  449. if (!subdir)
  450. return;
  451. for (const char *const *a = aAppendList; *a; ++a) {
  452. subdir->AppendNative(nsDependentCString(*a));
  453. }
  454. bool exists;
  455. if (NS_SUCCEEDED(subdir->Exists(&exists)) && exists) {
  456. aDirectories.AppendObject(subdir);
  457. }
  458. }
  459. static void
  460. LoadDirsIntoArray(nsCOMArray<nsIFile>& aSourceDirs,
  461. const char *const* aAppendList,
  462. nsCOMArray<nsIFile>& aDirectories)
  463. {
  464. nsCOMPtr<nsIFile> appended;
  465. bool exists;
  466. for (int32_t i = 0; i < aSourceDirs.Count(); ++i) {
  467. aSourceDirs[i]->Clone(getter_AddRefs(appended));
  468. if (!appended)
  469. continue;
  470. nsAutoCString leaf;
  471. appended->GetNativeLeafName(leaf);
  472. if (!Substring(leaf, leaf.Length() - 4).EqualsLiteral(".xpi")) {
  473. LoadDirIntoArray(appended,
  474. aAppendList,
  475. aDirectories);
  476. }
  477. else if (NS_SUCCEEDED(appended->Exists(&exists)) && exists)
  478. aDirectories.AppendObject(appended);
  479. }
  480. }
  481. NS_IMETHODIMP
  482. nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult)
  483. {
  484. nsresult rv;
  485. nsCOMPtr<nsISimpleEnumerator> appEnum;
  486. nsCOMPtr<nsIDirectoryServiceProvider2>
  487. appP2(do_QueryInterface(mAppProvider));
  488. if (appP2) {
  489. rv = appP2->GetFiles(aProperty, getter_AddRefs(appEnum));
  490. if (NS_FAILED(rv)) {
  491. appEnum = nullptr;
  492. }
  493. else if (rv != NS_SUCCESS_AGGREGATE_RESULT) {
  494. appEnum.forget(aResult);
  495. return NS_OK;
  496. }
  497. }
  498. nsCOMPtr<nsISimpleEnumerator> xreEnum;
  499. rv = GetFilesInternal(aProperty, getter_AddRefs(xreEnum));
  500. if (NS_FAILED(rv)) {
  501. if (appEnum) {
  502. appEnum.forget(aResult);
  503. return NS_SUCCESS_AGGREGATE_RESULT;
  504. }
  505. return rv;
  506. }
  507. rv = NS_NewUnionEnumerator(aResult, appEnum, xreEnum);
  508. if (NS_FAILED(rv))
  509. return rv;
  510. return NS_SUCCESS_AGGREGATE_RESULT;
  511. }
  512. static void
  513. RegisterExtensionInterpositions(nsINIParser &parser)
  514. {
  515. if (!mozilla::Preferences::GetBool("extensions.interposition.enabled", false))
  516. return;
  517. nsCOMPtr<nsIAddonInterposition> interposition =
  518. do_GetService("@mozilla.org/addons/multiprocess-shims;1");
  519. nsresult rv;
  520. int32_t i = 0;
  521. do {
  522. nsAutoCString buf("Extension");
  523. buf.AppendInt(i++);
  524. nsAutoCString addonId;
  525. rv = parser.GetString("MultiprocessIncompatibleExtensions", buf.get(), addonId);
  526. if (NS_FAILED(rv))
  527. return;
  528. if (!xpc::SetAddonInterposition(addonId, interposition))
  529. continue;
  530. if (!xpc::AllowCPOWsInAddon(addonId, true))
  531. continue;
  532. }
  533. while (true);
  534. }
  535. static void
  536. LoadExtensionDirectories(nsINIParser &parser,
  537. const char *aSection,
  538. nsCOMArray<nsIFile> &aDirectories,
  539. NSLocationType aType)
  540. {
  541. nsresult rv;
  542. int32_t i = 0;
  543. do {
  544. nsAutoCString buf("Extension");
  545. buf.AppendInt(i++);
  546. nsAutoCString path;
  547. rv = parser.GetString(aSection, buf.get(), path);
  548. if (NS_FAILED(rv))
  549. return;
  550. nsCOMPtr<nsIFile> dir = do_CreateInstance("@mozilla.org/file/local;1", &rv);
  551. if (NS_FAILED(rv))
  552. continue;
  553. rv = dir->SetPersistentDescriptor(path);
  554. if (NS_FAILED(rv))
  555. continue;
  556. aDirectories.AppendObject(dir);
  557. if (Substring(path, path.Length() - 4).EqualsLiteral(".xpi")) {
  558. XRE_AddJarManifestLocation(aType, dir);
  559. }
  560. else {
  561. nsCOMPtr<nsIFile> manifest =
  562. CloneAndAppend(dir, "chrome.manifest");
  563. XRE_AddManifestLocation(aType, manifest);
  564. }
  565. }
  566. while (true);
  567. }
  568. void
  569. nsXREDirProvider::LoadExtensionBundleDirectories()
  570. {
  571. if (!mozilla::Preferences::GetBool("extensions.defaultProviders.enabled", true))
  572. return;
  573. if (mProfileDir) {
  574. if (!gSafeMode) {
  575. nsCOMPtr<nsIFile> extensionsINI;
  576. mProfileDir->Clone(getter_AddRefs(extensionsINI));
  577. if (!extensionsINI)
  578. return;
  579. extensionsINI->AppendNative(NS_LITERAL_CSTRING("extensions.ini"));
  580. nsCOMPtr<nsIFile> extensionsINILF =
  581. do_QueryInterface(extensionsINI);
  582. if (!extensionsINILF)
  583. return;
  584. nsINIParser parser;
  585. nsresult rv = parser.Init(extensionsINILF);
  586. if (NS_FAILED(rv))
  587. return;
  588. RegisterExtensionInterpositions(parser);
  589. LoadExtensionDirectories(parser, "ExtensionDirs", mExtensionDirectories,
  590. NS_EXTENSION_LOCATION);
  591. LoadExtensionDirectories(parser, "ThemeDirs", mThemeDirectories,
  592. NS_SKIN_LOCATION);
  593. /* non-Firefox applications that use overrides in their default theme should
  594. * define AC_DEFINE(MOZ_SEPARATE_MANIFEST_FOR_THEME_OVERRIDES) in their
  595. * configure.in */
  596. #if defined(MOZ_BUILD_APP_IS_BROWSER) || defined(MOZ_SEPARATE_MANIFEST_FOR_THEME_OVERRIDES)
  597. } else {
  598. // In safe mode, still load the default theme directory:
  599. nsCOMPtr<nsIFile> themeManifest;
  600. mXULAppDir->Clone(getter_AddRefs(themeManifest));
  601. themeManifest->AppendNative(NS_LITERAL_CSTRING("extensions"));
  602. themeManifest->AppendNative(NS_LITERAL_CSTRING("{972ce4c6-7e08-4474-a285-3208198ce6fd}.xpi"));
  603. bool exists = false;
  604. if (NS_SUCCEEDED(themeManifest->Exists(&exists)) && exists) {
  605. XRE_AddJarManifestLocation(NS_SKIN_LOCATION, themeManifest);
  606. } else {
  607. themeManifest->SetNativeLeafName(NS_LITERAL_CSTRING("{972ce4c6-7e08-4474-a285-3208198ce6fd}"));
  608. themeManifest->AppendNative(NS_LITERAL_CSTRING("chrome.manifest"));
  609. XRE_AddManifestLocation(NS_SKIN_LOCATION, themeManifest);
  610. }
  611. #endif
  612. }
  613. }
  614. }
  615. static const char *const kAppendPrefDir[] = { "defaults", "preferences", nullptr };
  616. #ifdef DEBUG_bsmedberg
  617. static void
  618. DumpFileArray(const char *key,
  619. nsCOMArray<nsIFile> dirs)
  620. {
  621. fprintf(stderr, "nsXREDirProvider::GetFilesInternal(%s)\n", key);
  622. nsAutoCString path;
  623. for (int32_t i = 0; i < dirs.Count(); ++i) {
  624. dirs[i]->GetNativePath(path);
  625. fprintf(stderr, " %s\n", path.get());
  626. }
  627. }
  628. #endif // DEBUG_bsmedberg
  629. nsresult
  630. nsXREDirProvider::GetFilesInternal(const char* aProperty,
  631. nsISimpleEnumerator** aResult)
  632. {
  633. nsresult rv = NS_OK;
  634. *aResult = nullptr;
  635. if (!strcmp(aProperty, XRE_EXTENSIONS_DIR_LIST)) {
  636. nsCOMArray<nsIFile> directories;
  637. static const char *const kAppendNothing[] = { nullptr };
  638. LoadDirsIntoArray(mAppBundleDirectories,
  639. kAppendNothing, directories);
  640. LoadDirsIntoArray(mExtensionDirectories,
  641. kAppendNothing, directories);
  642. rv = NS_NewArrayEnumerator(aResult, directories);
  643. }
  644. else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
  645. nsCOMArray<nsIFile> directories;
  646. LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories);
  647. LoadDirsIntoArray(mAppBundleDirectories,
  648. kAppendPrefDir, directories);
  649. rv = NS_NewArrayEnumerator(aResult, directories);
  650. }
  651. else if (!strcmp(aProperty, NS_EXT_PREFS_DEFAULTS_DIR_LIST)) {
  652. nsCOMArray<nsIFile> directories;
  653. LoadDirsIntoArray(mExtensionDirectories,
  654. kAppendPrefDir, directories);
  655. if (mProfileDir) {
  656. nsCOMPtr<nsIFile> overrideFile;
  657. mProfileDir->Clone(getter_AddRefs(overrideFile));
  658. overrideFile->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
  659. bool exists;
  660. if (NS_SUCCEEDED(overrideFile->Exists(&exists)) && exists)
  661. directories.AppendObject(overrideFile);
  662. }
  663. rv = NS_NewArrayEnumerator(aResult, directories);
  664. }
  665. else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) {
  666. // NS_APP_CHROME_DIR_LIST is only used to get default (native) icons
  667. // for OS window decoration.
  668. static const char *const kAppendChromeDir[] = { "chrome", nullptr };
  669. nsCOMArray<nsIFile> directories;
  670. LoadDirIntoArray(mXULAppDir,
  671. kAppendChromeDir,
  672. directories);
  673. LoadDirsIntoArray(mAppBundleDirectories,
  674. kAppendChromeDir,
  675. directories);
  676. LoadDirsIntoArray(mExtensionDirectories,
  677. kAppendChromeDir,
  678. directories);
  679. rv = NS_NewArrayEnumerator(aResult, directories);
  680. }
  681. else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) {
  682. nsCOMArray<nsIFile> directories;
  683. if (mozilla::Preferences::GetBool("plugins.load_appdir_plugins", false)) {
  684. nsCOMPtr<nsIFile> appdir;
  685. rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(appdir));
  686. if (NS_SUCCEEDED(rv)) {
  687. appdir->SetNativeLeafName(NS_LITERAL_CSTRING("plugins"));
  688. directories.AppendObject(appdir);
  689. }
  690. }
  691. static const char *const kAppendPlugins[] = { "plugins", nullptr };
  692. // The root dirserviceprovider does quite a bit for us: we're mainly
  693. // interested in xulapp and extension-provided plugins.
  694. LoadDirsIntoArray(mAppBundleDirectories,
  695. kAppendPlugins,
  696. directories);
  697. LoadDirsIntoArray(mExtensionDirectories,
  698. kAppendPlugins,
  699. directories);
  700. if (mProfileDir) {
  701. nsCOMArray<nsIFile> profileDir;
  702. profileDir.AppendObject(mProfileDir);
  703. LoadDirsIntoArray(profileDir,
  704. kAppendPlugins,
  705. directories);
  706. }
  707. rv = NS_NewArrayEnumerator(aResult, directories);
  708. NS_ENSURE_SUCCESS(rv, rv);
  709. rv = NS_SUCCESS_AGGREGATE_RESULT;
  710. }
  711. else
  712. rv = NS_ERROR_FAILURE;
  713. return rv;
  714. }
  715. NS_IMETHODIMP
  716. nsXREDirProvider::GetDirectory(nsIFile* *aResult)
  717. {
  718. NS_ENSURE_TRUE(mProfileDir, NS_ERROR_NOT_INITIALIZED);
  719. return mProfileDir->Clone(aResult);
  720. }
  721. NS_IMETHODIMP
  722. nsXREDirProvider::DoStartup()
  723. {
  724. if (!mProfileNotified) {
  725. nsCOMPtr<nsIObserverService> obsSvc =
  726. mozilla::services::GetObserverService();
  727. if (!obsSvc) return NS_ERROR_FAILURE;
  728. mProfileNotified = true;
  729. /*
  730. Setup prefs before profile-do-change to be able to use them to track
  731. crashes and because we want to begin crash tracking before other code run
  732. from this notification since they may cause crashes.
  733. */
  734. nsresult rv = mozilla::Preferences::ResetAndReadUserPrefs();
  735. if (NS_FAILED(rv)) NS_WARNING("Failed to setup pref service.");
  736. bool safeModeNecessary = false;
  737. nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
  738. if (appStartup) {
  739. rv = appStartup->TrackStartupCrashBegin(&safeModeNecessary);
  740. if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE)
  741. NS_WARNING("Error while beginning startup crash tracking");
  742. if (!gSafeMode && safeModeNecessary) {
  743. appStartup->RestartInSafeMode(nsIAppStartup::eForceQuit);
  744. return NS_OK;
  745. }
  746. }
  747. static const char16_t kStartup[] = {'s','t','a','r','t','u','p','\0'};
  748. obsSvc->NotifyObservers(nullptr, "profile-do-change", kStartup);
  749. // Init the Extension Manager
  750. nsCOMPtr<nsIObserver> em = do_GetService("@mozilla.org/addons/integration;1");
  751. if (em) {
  752. em->Observe(nullptr, "addons-startup", nullptr);
  753. } else {
  754. NS_WARNING("Failed to create Addons Manager.");
  755. }
  756. LoadExtensionBundleDirectories();
  757. obsSvc->NotifyObservers(nullptr, "load-extension-defaults", nullptr);
  758. obsSvc->NotifyObservers(nullptr, "profile-after-change", kStartup);
  759. // Any component that has registered for the profile-after-change category
  760. // should also be created at this time.
  761. (void)NS_CreateServicesFromCategory("profile-after-change", nullptr,
  762. "profile-after-change");
  763. if (gSafeMode && safeModeNecessary) {
  764. static const char16_t kCrashed[] = {'c','r','a','s','h','e','d','\0'};
  765. obsSvc->NotifyObservers(nullptr, "safemode-forced", kCrashed);
  766. }
  767. // 1 = Regular mode, 2 = Safe mode, 3 = Safe mode forced
  768. int mode = 1;
  769. if (gSafeMode) {
  770. if (safeModeNecessary)
  771. mode = 3;
  772. else
  773. mode = 2;
  774. }
  775. obsSvc->NotifyObservers(nullptr, "profile-initial-state", nullptr);
  776. }
  777. return NS_OK;
  778. }
  779. void
  780. nsXREDirProvider::DoShutdown()
  781. {
  782. PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
  783. if (mProfileNotified) {
  784. nsCOMPtr<nsIObserverService> obsSvc =
  785. mozilla::services::GetObserverService();
  786. NS_ASSERTION(obsSvc, "No observer service?");
  787. if (obsSvc) {
  788. static const char16_t kShutdownPersist[] = u"shutdown-persist";
  789. obsSvc->NotifyObservers(nullptr, "profile-change-net-teardown", kShutdownPersist);
  790. obsSvc->NotifyObservers(nullptr, "profile-change-teardown", kShutdownPersist);
  791. // Phase 2c: Now that things are torn down, force JS GC so that things which depend on
  792. // resources which are about to go away in "profile-before-change" are destroyed first.
  793. if (JSContext* cx = dom::danger::GetJSContext()) {
  794. JS_GC(cx);
  795. }
  796. // Phase 3: Notify observers of a profile change
  797. obsSvc->NotifyObservers(nullptr, "profile-before-change", kShutdownPersist);
  798. obsSvc->NotifyObservers(nullptr, "profile-before-change-qm", kShutdownPersist);
  799. obsSvc->NotifyObservers(nullptr, "profile-before-change-telemetry", kShutdownPersist);
  800. }
  801. mProfileNotified = false;
  802. }
  803. }
  804. #ifdef XP_WIN
  805. static nsresult
  806. GetShellFolderPath(int folder, nsAString& _retval)
  807. {
  808. wchar_t* buf;
  809. uint32_t bufLength = _retval.GetMutableData(&buf, MAXPATHLEN + 3);
  810. NS_ENSURE_TRUE(bufLength >= (MAXPATHLEN + 3), NS_ERROR_OUT_OF_MEMORY);
  811. nsresult rv = NS_OK;
  812. LPITEMIDLIST pItemIDList = nullptr;
  813. if (SUCCEEDED(SHGetSpecialFolderLocation(nullptr, folder, &pItemIDList)) &&
  814. SHGetPathFromIDListW(pItemIDList, buf)) {
  815. // We're going to use wcslen (wcsnlen not available in msvc7.1) so make
  816. // sure to null terminate.
  817. buf[bufLength - 1] = L'\0';
  818. _retval.SetLength(wcslen(buf));
  819. } else {
  820. _retval.SetLength(0);
  821. rv = NS_ERROR_NOT_AVAILABLE;
  822. }
  823. CoTaskMemFree(pItemIDList);
  824. return rv;
  825. }
  826. /**
  827. * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
  828. * querying the registry when the call to SHGetSpecialFolderLocation or
  829. * SHGetPathFromIDListW is unable to provide these paths (Bug 513958).
  830. */
  831. static nsresult
  832. GetRegWindowsAppDataFolder(bool aLocal, nsAString& _retval)
  833. {
  834. HKEY key;
  835. NS_NAMED_LITERAL_STRING(keyName,
  836. "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
  837. DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0, KEY_READ,
  838. &key);
  839. if (res != ERROR_SUCCESS) {
  840. _retval.SetLength(0);
  841. return NS_ERROR_NOT_AVAILABLE;
  842. }
  843. DWORD type, size;
  844. res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
  845. nullptr, &type, nullptr, &size);
  846. // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
  847. // buffer size must not equal 0, and the buffer size be a multiple of 2.
  848. if (res != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0) {
  849. ::RegCloseKey(key);
  850. _retval.SetLength(0);
  851. return NS_ERROR_NOT_AVAILABLE;
  852. }
  853. // |size| may or may not include room for the terminating null character
  854. DWORD resultLen = size / 2;
  855. if (!_retval.SetLength(resultLen, mozilla::fallible)) {
  856. ::RegCloseKey(key);
  857. _retval.SetLength(0);
  858. return NS_ERROR_NOT_AVAILABLE;
  859. }
  860. nsAString::iterator begin;
  861. _retval.BeginWriting(begin);
  862. res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
  863. nullptr, nullptr, (LPBYTE) begin.get(), &size);
  864. ::RegCloseKey(key);
  865. if (res != ERROR_SUCCESS) {
  866. _retval.SetLength(0);
  867. return NS_ERROR_NOT_AVAILABLE;
  868. }
  869. if (!_retval.CharAt(resultLen - 1)) {
  870. // It was already null terminated.
  871. _retval.Truncate(resultLen - 1);
  872. }
  873. return NS_OK;
  874. }
  875. static bool
  876. GetCachedHash(HKEY rootKey, const nsAString &regPath, const nsAString &path,
  877. nsAString &cachedHash)
  878. {
  879. HKEY baseKey;
  880. if (RegOpenKeyExW(rootKey, reinterpret_cast<const wchar_t*>(regPath.BeginReading()), 0, KEY_READ, &baseKey) !=
  881. ERROR_SUCCESS) {
  882. return false;
  883. }
  884. wchar_t cachedHashRaw[512];
  885. DWORD bufferSize = sizeof(cachedHashRaw);
  886. LONG result = RegQueryValueExW(baseKey, reinterpret_cast<const wchar_t*>(path.BeginReading()), 0, nullptr,
  887. (LPBYTE)cachedHashRaw, &bufferSize);
  888. RegCloseKey(baseKey);
  889. if (result == ERROR_SUCCESS) {
  890. cachedHash.Assign(cachedHashRaw);
  891. }
  892. return ERROR_SUCCESS == result;
  893. }
  894. #endif
  895. nsresult
  896. nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult)
  897. {
  898. nsCOMPtr<nsIFile> updRoot;
  899. nsCOMPtr<nsIFile> appFile;
  900. bool per = false;
  901. nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &per, getter_AddRefs(appFile));
  902. NS_ENSURE_SUCCESS(rv, rv);
  903. rv = appFile->GetParent(getter_AddRefs(updRoot));
  904. NS_ENSURE_SUCCESS(rv, rv);
  905. #ifdef XP_WIN
  906. nsAutoString pathHash;
  907. bool pathHashResult = false;
  908. bool hasVendor = gAppData->vendor && strlen(gAppData->vendor) != 0;
  909. nsAutoString appDirPath;
  910. if (SUCCEEDED(updRoot->GetPath(appDirPath))) {
  911. // Figure out where we should check for a cached hash value. If the
  912. // application doesn't have the nsXREAppData vendor value defined check
  913. // under SOFTWARE\Mozilla.
  914. wchar_t regPath[1024] = { L'\0' };
  915. swprintf_s(regPath, mozilla::ArrayLength(regPath), L"SOFTWARE\\%S\\%S\\TaskBarIDs",
  916. (hasVendor ? gAppData->vendor : "Mozilla"), MOZ_APP_BASENAME);
  917. // If we pre-computed the hash, grab it from the registry.
  918. pathHashResult = GetCachedHash(HKEY_LOCAL_MACHINE,
  919. nsDependentString(regPath), appDirPath,
  920. pathHash);
  921. if (!pathHashResult) {
  922. pathHashResult = GetCachedHash(HKEY_CURRENT_USER,
  923. nsDependentString(regPath), appDirPath,
  924. pathHash);
  925. }
  926. }
  927. // Get the local app data directory and if a vendor name exists append it.
  928. // If only a product name exists, append it. If neither exist fallback to
  929. // old handling. We don't use the product name on purpose because we want a
  930. // shared update directory for different apps run from the same path.
  931. nsCOMPtr<nsIFile> localDir;
  932. if (pathHashResult && (hasVendor || gAppData->name) &&
  933. NS_SUCCEEDED(GetUserDataDirectoryHome(getter_AddRefs(localDir), true)) &&
  934. NS_SUCCEEDED(localDir->AppendNative(nsDependentCString(hasVendor ?
  935. gAppData->vendor : gAppData->name))) &&
  936. NS_SUCCEEDED(localDir->Append(NS_LITERAL_STRING("updates"))) &&
  937. NS_SUCCEEDED(localDir->Append(pathHash))) {
  938. localDir.forget(aResult);
  939. return NS_OK;
  940. }
  941. nsAutoString appPath;
  942. rv = updRoot->GetPath(appPath);
  943. NS_ENSURE_SUCCESS(rv, rv);
  944. // AppDir may be a short path. Convert to long path to make sure
  945. // the consistency of the update folder location
  946. nsString longPath;
  947. wchar_t* buf;
  948. uint32_t bufLength = longPath.GetMutableData(&buf, MAXPATHLEN);
  949. NS_ENSURE_TRUE(bufLength >= MAXPATHLEN, NS_ERROR_OUT_OF_MEMORY);
  950. DWORD len = GetLongPathNameW(appPath.get(), buf, bufLength);
  951. // Failing GetLongPathName() is not fatal.
  952. if (len <= 0 || len >= bufLength)
  953. longPath.Assign(appPath);
  954. else
  955. longPath.SetLength(len);
  956. // Use <UserLocalDataDir>\updates\<relative path to app dir from
  957. // Program Files> if app dir is under Program Files to avoid the
  958. // folder virtualization mess on Windows Vista
  959. nsAutoString programFiles;
  960. rv = GetShellFolderPath(CSIDL_PROGRAM_FILES, programFiles);
  961. NS_ENSURE_SUCCESS(rv, rv);
  962. programFiles.Append('\\');
  963. uint32_t programFilesLen = programFiles.Length();
  964. nsAutoString programName;
  965. if (_wcsnicmp(programFiles.get(), longPath.get(), programFilesLen) == 0) {
  966. programName = Substring(longPath, programFilesLen);
  967. } else {
  968. // We need the update root directory to live outside of the installation
  969. // directory, because otherwise the updater writing the log file can cause
  970. // the directory to be locked, which prevents it from being replaced after
  971. // background updates.
  972. programName.AssignASCII(MOZ_APP_NAME);
  973. }
  974. rv = GetUserLocalDataDirectory(getter_AddRefs(updRoot));
  975. NS_ENSURE_SUCCESS(rv, rv);
  976. rv = updRoot->AppendRelativePath(programName);
  977. NS_ENSURE_SUCCESS(rv, rv);
  978. #endif // XP_WIN
  979. updRoot.forget(aResult);
  980. return NS_OK;
  981. }
  982. nsresult
  983. nsXREDirProvider::GetProfileStartupDir(nsIFile* *aResult)
  984. {
  985. if (mProfileDir)
  986. return mProfileDir->Clone(aResult);
  987. if (mAppProvider) {
  988. nsCOMPtr<nsIFile> needsclone;
  989. bool dummy;
  990. nsresult rv = mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP,
  991. &dummy,
  992. getter_AddRefs(needsclone));
  993. if (NS_SUCCEEDED(rv))
  994. return needsclone->Clone(aResult);
  995. }
  996. return NS_ERROR_FAILURE;
  997. }
  998. nsresult
  999. nsXREDirProvider::GetProfileDir(nsIFile* *aResult)
  1000. {
  1001. if (mProfileDir) {
  1002. if (!mProfileNotified)
  1003. return NS_ERROR_FAILURE;
  1004. return mProfileDir->Clone(aResult);
  1005. }
  1006. if (mAppProvider) {
  1007. nsCOMPtr<nsIFile> needsclone;
  1008. bool dummy;
  1009. nsresult rv = mAppProvider->GetFile(NS_APP_USER_PROFILE_50_DIR,
  1010. &dummy,
  1011. getter_AddRefs(needsclone));
  1012. if (NS_SUCCEEDED(rv))
  1013. return needsclone->Clone(aResult);
  1014. }
  1015. return NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, aResult);
  1016. }
  1017. nsresult
  1018. nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal)
  1019. {
  1020. // Copied from nsAppFileLocationProvider (more or less)
  1021. nsresult rv;
  1022. nsCOMPtr<nsIFile> localDir;
  1023. #if defined(XP_WIN)
  1024. nsString path;
  1025. if (aLocal) {
  1026. rv = GetShellFolderPath(CSIDL_LOCAL_APPDATA, path);
  1027. if (NS_FAILED(rv))
  1028. rv = GetRegWindowsAppDataFolder(aLocal, path);
  1029. }
  1030. if (!aLocal || NS_FAILED(rv)) {
  1031. rv = GetShellFolderPath(CSIDL_APPDATA, path);
  1032. if (NS_FAILED(rv)) {
  1033. if (!aLocal)
  1034. rv = GetRegWindowsAppDataFolder(aLocal, path);
  1035. }
  1036. }
  1037. NS_ENSURE_SUCCESS(rv, rv);
  1038. rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
  1039. #elif defined(XP_UNIX)
  1040. const char* homeDir = getenv("HOME");
  1041. if (!homeDir || !*homeDir)
  1042. return NS_ERROR_FAILURE;
  1043. if (aLocal) {
  1044. // If $XDG_CACHE_HOME is defined use it, otherwise use $HOME/.cache.
  1045. const char* cacheHome = getenv("XDG_CACHE_HOME");
  1046. if (cacheHome && *cacheHome) {
  1047. rv = NS_NewNativeLocalFile(nsDependentCString(cacheHome), true,
  1048. getter_AddRefs(localDir));
  1049. } else {
  1050. rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
  1051. getter_AddRefs(localDir));
  1052. if (NS_SUCCEEDED(rv))
  1053. rv = localDir->AppendNative(NS_LITERAL_CSTRING(".cache"));
  1054. }
  1055. } else {
  1056. rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
  1057. getter_AddRefs(localDir));
  1058. }
  1059. #else
  1060. #error "Don't know how to get product dir on your platform"
  1061. #endif
  1062. NS_IF_ADDREF(*aFile = localDir);
  1063. return rv;
  1064. }
  1065. nsresult
  1066. nsXREDirProvider::GetSysUserExtensionsDirectory(nsIFile** aFile)
  1067. {
  1068. nsCOMPtr<nsIFile> localDir;
  1069. nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
  1070. NS_ENSURE_SUCCESS(rv, rv);
  1071. rv = AppendSysUserExtensionPath(localDir);
  1072. NS_ENSURE_SUCCESS(rv, rv);
  1073. rv = EnsureDirectoryExists(localDir);
  1074. NS_ENSURE_SUCCESS(rv, rv);
  1075. localDir.forget(aFile);
  1076. return NS_OK;
  1077. }
  1078. #if defined(XP_UNIX)
  1079. nsresult
  1080. nsXREDirProvider::GetSystemExtensionsDirectory(nsIFile** aFile)
  1081. {
  1082. nsresult rv;
  1083. nsCOMPtr<nsIFile> localDir;
  1084. rv = GetSystemParentDirectory(getter_AddRefs(localDir));
  1085. if (NS_SUCCEEDED(rv)) {
  1086. NS_NAMED_LITERAL_CSTRING(sExtensions,
  1087. "extensions"
  1088. );
  1089. rv = localDir->AppendNative(sExtensions);
  1090. if (NS_SUCCEEDED(rv)) {
  1091. localDir.forget(aFile);
  1092. }
  1093. }
  1094. return rv;
  1095. }
  1096. #endif
  1097. nsresult
  1098. nsXREDirProvider::GetUserDataDirectory(nsIFile** aFile, bool aLocal,
  1099. const nsACString* aProfileName,
  1100. const nsACString* aAppName,
  1101. const nsACString* aVendorName)
  1102. {
  1103. nsCOMPtr<nsIFile> localDir;
  1104. nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), aLocal);
  1105. NS_ENSURE_SUCCESS(rv, rv);
  1106. rv = AppendProfilePath(localDir, aProfileName, aAppName, aVendorName, aLocal);
  1107. NS_ENSURE_SUCCESS(rv, rv);
  1108. #ifdef DEBUG_jungshik
  1109. nsAutoCString cwd;
  1110. localDir->GetNativePath(cwd);
  1111. printf("nsXREDirProvider::GetUserDataDirectory: %s\n", cwd.get());
  1112. #endif
  1113. rv = EnsureDirectoryExists(localDir);
  1114. NS_ENSURE_SUCCESS(rv, rv);
  1115. localDir.forget(aFile);
  1116. return NS_OK;
  1117. }
  1118. nsresult
  1119. nsXREDirProvider::EnsureDirectoryExists(nsIFile* aDirectory)
  1120. {
  1121. bool exists;
  1122. nsresult rv = aDirectory->Exists(&exists);
  1123. NS_ENSURE_SUCCESS(rv, rv);
  1124. #ifdef DEBUG_jungshik
  1125. if (!exists) {
  1126. nsAutoCString cwd;
  1127. aDirectory->GetNativePath(cwd);
  1128. printf("nsXREDirProvider::EnsureDirectoryExists: %s does not\n", cwd.get());
  1129. }
  1130. #endif
  1131. if (!exists)
  1132. rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0700);
  1133. #ifdef DEBUG_jungshik
  1134. if (NS_FAILED(rv))
  1135. NS_WARNING("nsXREDirProvider::EnsureDirectoryExists: create failed");
  1136. #endif
  1137. return rv;
  1138. }
  1139. nsresult
  1140. nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile)
  1141. {
  1142. NS_ASSERTION(aFile, "Null pointer!");
  1143. nsresult rv;
  1144. #if defined(XP_WIN)
  1145. static const char* const sXR = "Mozilla";
  1146. rv = aFile->AppendNative(nsDependentCString(sXR));
  1147. NS_ENSURE_SUCCESS(rv, rv);
  1148. static const char* const sExtensions = "Extensions";
  1149. rv = aFile->AppendNative(nsDependentCString(sExtensions));
  1150. NS_ENSURE_SUCCESS(rv, rv);
  1151. #elif defined(XP_UNIX)
  1152. static const char* const sXR = ".mozilla";
  1153. rv = aFile->AppendNative(nsDependentCString(sXR));
  1154. NS_ENSURE_SUCCESS(rv, rv);
  1155. static const char* const sExtensions = "extensions";
  1156. rv = aFile->AppendNative(nsDependentCString(sExtensions));
  1157. NS_ENSURE_SUCCESS(rv, rv);
  1158. #else
  1159. #error "Don't know how to get XRE user extension path on your platform"
  1160. #endif
  1161. return NS_OK;
  1162. }
  1163. nsresult
  1164. nsXREDirProvider::AppendProfilePath(nsIFile* aFile,
  1165. const nsACString* aProfileName,
  1166. const nsACString* aAppName,
  1167. const nsACString* aVendorName,
  1168. bool aLocal)
  1169. {
  1170. NS_ASSERTION(aFile, "Null pointer!");
  1171. if (!gAppData) {
  1172. return NS_ERROR_FAILURE;
  1173. }
  1174. nsAutoCString profile;
  1175. nsAutoCString appName;
  1176. nsAutoCString vendor;
  1177. if (aProfileName && !aProfileName->IsEmpty()) {
  1178. profile = *aProfileName;
  1179. } else if (aAppName) {
  1180. appName = *aAppName;
  1181. if (aVendorName) {
  1182. vendor = *aVendorName;
  1183. }
  1184. } else if (gAppData->profile) {
  1185. profile = gAppData->profile;
  1186. } else {
  1187. appName = gAppData->name;
  1188. vendor = gAppData->vendor;
  1189. }
  1190. nsresult rv;
  1191. #if defined(XP_WIN)
  1192. if (!profile.IsEmpty()) {
  1193. rv = AppendProfileString(aFile, profile.get());
  1194. }
  1195. else {
  1196. if (!vendor.IsEmpty()) {
  1197. rv = aFile->AppendNative(vendor);
  1198. NS_ENSURE_SUCCESS(rv, rv);
  1199. }
  1200. rv = aFile->AppendNative(appName);
  1201. }
  1202. NS_ENSURE_SUCCESS(rv, rv);
  1203. #elif defined(XP_UNIX)
  1204. nsAutoCString folder;
  1205. // Make it hidden (by starting with "."), except when local (the
  1206. // profile is already under ~/.cache or XDG_CACHE_HOME).
  1207. if (!aLocal)
  1208. folder.Assign('.');
  1209. if (!profile.IsEmpty()) {
  1210. // Skip any leading path characters
  1211. const char* profileStart = profile.get();
  1212. while (*profileStart == '/' || *profileStart == '\\')
  1213. profileStart++;
  1214. // On the off chance that someone wanted their folder to be hidden don't
  1215. // let it become ".."
  1216. if (*profileStart == '.' && !aLocal)
  1217. profileStart++;
  1218. folder.Append(profileStart);
  1219. ToLowerCase(folder);
  1220. rv = AppendProfileString(aFile, folder.BeginReading());
  1221. }
  1222. else {
  1223. if (!vendor.IsEmpty()) {
  1224. folder.Append(vendor);
  1225. ToLowerCase(folder);
  1226. rv = aFile->AppendNative(folder);
  1227. NS_ENSURE_SUCCESS(rv, rv);
  1228. folder.Truncate();
  1229. }
  1230. folder.Append(appName);
  1231. ToLowerCase(folder);
  1232. rv = aFile->AppendNative(folder);
  1233. }
  1234. NS_ENSURE_SUCCESS(rv, rv);
  1235. #else
  1236. #error "Don't know how to get profile path on your platform"
  1237. #endif
  1238. return NS_OK;
  1239. }
  1240. nsresult
  1241. nsXREDirProvider::AppendProfileString(nsIFile* aFile, const char* aPath)
  1242. {
  1243. NS_ASSERTION(aFile, "Null file!");
  1244. NS_ASSERTION(aPath, "Null path!");
  1245. nsAutoCString pathDup(aPath);
  1246. char* path = pathDup.BeginWriting();
  1247. nsresult rv;
  1248. char* subdir;
  1249. while ((subdir = NS_strtok("/\\", &path))) {
  1250. rv = aFile->AppendNative(nsDependentCString(subdir));
  1251. NS_ENSURE_SUCCESS(rv, rv);
  1252. }
  1253. return NS_OK;
  1254. }