nsChromeRegistry.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. /* -*- Mode: C++; tab-width: 4; 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 "nsChromeRegistry.h"
  6. #include "nsChromeRegistryChrome.h"
  7. #include "nsChromeRegistryContent.h"
  8. #include "prprf.h"
  9. #include "nsCOMPtr.h"
  10. #include "nsError.h"
  11. #include "nsEscape.h"
  12. #include "nsNetUtil.h"
  13. #include "nsIURL.h"
  14. #include "nsString.h"
  15. #include "nsQueryObject.h"
  16. #include "mozilla/dom/URL.h"
  17. #include "nsIConsoleService.h"
  18. #include "nsIDocument.h"
  19. #include "nsIDOMDocument.h"
  20. #include "nsIDOMLocation.h"
  21. #include "nsIDOMWindowCollection.h"
  22. #include "nsIDOMWindow.h"
  23. #include "nsIObserverService.h"
  24. #include "nsIPresShell.h"
  25. #include "nsIScriptError.h"
  26. #include "nsIWindowMediator.h"
  27. #include "nsIPrefService.h"
  28. #include "mozilla/StyleSheet.h"
  29. #include "mozilla/StyleSheetInlines.h"
  30. #include "unicode/uloc.h"
  31. nsChromeRegistry* nsChromeRegistry::gChromeRegistry;
  32. // DO NOT use namespace mozilla; it'll break due to a naming conflict between
  33. // mozilla::TextRange and a TextRange in OSX headers.
  34. using mozilla::StyleSheet;
  35. using mozilla::dom::IsChromeURI;
  36. ////////////////////////////////////////////////////////////////////////////////
  37. void
  38. nsChromeRegistry::LogMessage(const char* aMsg, ...)
  39. {
  40. nsCOMPtr<nsIConsoleService> console
  41. (do_GetService(NS_CONSOLESERVICE_CONTRACTID));
  42. if (!console)
  43. return;
  44. va_list args;
  45. va_start(args, aMsg);
  46. char* formatted = PR_vsmprintf(aMsg, args);
  47. va_end(args);
  48. if (!formatted)
  49. return;
  50. console->LogStringMessage(NS_ConvertUTF8toUTF16(formatted).get());
  51. PR_smprintf_free(formatted);
  52. }
  53. void
  54. nsChromeRegistry::LogMessageWithContext(nsIURI* aURL, uint32_t aLineNumber, uint32_t flags,
  55. const char* aMsg, ...)
  56. {
  57. nsresult rv;
  58. nsCOMPtr<nsIConsoleService> console
  59. (do_GetService(NS_CONSOLESERVICE_CONTRACTID));
  60. nsCOMPtr<nsIScriptError> error
  61. (do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
  62. if (!console || !error)
  63. return;
  64. va_list args;
  65. va_start(args, aMsg);
  66. char* formatted = PR_vsmprintf(aMsg, args);
  67. va_end(args);
  68. if (!formatted)
  69. return;
  70. nsCString spec;
  71. if (aURL)
  72. aURL->GetSpec(spec);
  73. rv = error->Init(NS_ConvertUTF8toUTF16(formatted),
  74. NS_ConvertUTF8toUTF16(spec),
  75. EmptyString(),
  76. aLineNumber, 0, flags, "chrome registration");
  77. PR_smprintf_free(formatted);
  78. if (NS_FAILED(rv))
  79. return;
  80. console->LogMessage(error);
  81. }
  82. nsChromeRegistry::~nsChromeRegistry()
  83. {
  84. gChromeRegistry = nullptr;
  85. }
  86. NS_INTERFACE_MAP_BEGIN(nsChromeRegistry)
  87. NS_INTERFACE_MAP_ENTRY(nsIChromeRegistry)
  88. NS_INTERFACE_MAP_ENTRY(nsIXULChromeRegistry)
  89. NS_INTERFACE_MAP_ENTRY(nsIToolkitChromeRegistry)
  90. #ifdef MOZ_XUL
  91. NS_INTERFACE_MAP_ENTRY(nsIXULOverlayProvider)
  92. #endif
  93. NS_INTERFACE_MAP_ENTRY(nsIObserver)
  94. NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
  95. NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIChromeRegistry)
  96. NS_INTERFACE_MAP_END
  97. NS_IMPL_ADDREF(nsChromeRegistry)
  98. NS_IMPL_RELEASE(nsChromeRegistry)
  99. ////////////////////////////////////////////////////////////////////////////////
  100. // nsIChromeRegistry methods:
  101. already_AddRefed<nsIChromeRegistry>
  102. nsChromeRegistry::GetService()
  103. {
  104. if (!gChromeRegistry)
  105. {
  106. // We don't actually want this ref, we just want the service to
  107. // initialize if it hasn't already.
  108. nsCOMPtr<nsIChromeRegistry> reg(
  109. do_GetService(NS_CHROMEREGISTRY_CONTRACTID));
  110. if (!gChromeRegistry)
  111. return nullptr;
  112. }
  113. nsCOMPtr<nsIChromeRegistry> registry = gChromeRegistry;
  114. return registry.forget();
  115. }
  116. nsresult
  117. nsChromeRegistry::Init()
  118. {
  119. // This initialization process is fairly complicated and may cause reentrant
  120. // getservice calls to resolve chrome URIs (especially locale files). We
  121. // don't want that, so we inform the protocol handler about our existence
  122. // before we are actually fully initialized.
  123. gChromeRegistry = this;
  124. mInitialized = true;
  125. return NS_OK;
  126. }
  127. nsresult
  128. nsChromeRegistry::GetProviderAndPath(nsIURL* aChromeURL,
  129. nsACString& aProvider, nsACString& aPath)
  130. {
  131. nsresult rv;
  132. #ifdef DEBUG
  133. bool isChrome;
  134. aChromeURL->SchemeIs("chrome", &isChrome);
  135. NS_ASSERTION(isChrome, "Non-chrome URI?");
  136. #endif
  137. nsAutoCString path;
  138. rv = aChromeURL->GetPath(path);
  139. NS_ENSURE_SUCCESS(rv, rv);
  140. if (path.Length() < 3) {
  141. LogMessage("Invalid chrome URI: %s", path.get());
  142. return NS_ERROR_FAILURE;
  143. }
  144. path.SetLength(nsUnescapeCount(path.BeginWriting()));
  145. NS_ASSERTION(path.First() == '/', "Path should always begin with a slash!");
  146. int32_t slash = path.FindChar('/', 1);
  147. if (slash == 1) {
  148. LogMessage("Invalid chrome URI: %s", path.get());
  149. return NS_ERROR_FAILURE;
  150. }
  151. if (slash == -1) {
  152. aPath.Truncate();
  153. }
  154. else {
  155. if (slash == (int32_t) path.Length() - 1)
  156. aPath.Truncate();
  157. else
  158. aPath.Assign(path.get() + slash + 1, path.Length() - slash - 1);
  159. --slash;
  160. }
  161. aProvider.Assign(path.get() + 1, slash);
  162. return NS_OK;
  163. }
  164. nsresult
  165. nsChromeRegistry::Canonify(nsIURL* aChromeURL)
  166. {
  167. NS_NAMED_LITERAL_CSTRING(kSlash, "/");
  168. nsresult rv;
  169. nsAutoCString provider, path;
  170. rv = GetProviderAndPath(aChromeURL, provider, path);
  171. NS_ENSURE_SUCCESS(rv, rv);
  172. if (path.IsEmpty()) {
  173. nsAutoCString package;
  174. rv = aChromeURL->GetHost(package);
  175. NS_ENSURE_SUCCESS(rv, rv);
  176. // we re-use the "path" local string to build a new URL path
  177. path.Assign(kSlash + provider + kSlash + package);
  178. if (provider.EqualsLiteral("content")) {
  179. path.AppendLiteral(".xul");
  180. }
  181. else if (provider.EqualsLiteral("locale")) {
  182. path.AppendLiteral(".dtd");
  183. }
  184. else if (provider.EqualsLiteral("skin")) {
  185. path.AppendLiteral(".css");
  186. }
  187. else {
  188. return NS_ERROR_INVALID_ARG;
  189. }
  190. aChromeURL->SetPath(path);
  191. }
  192. else {
  193. // path is already unescaped once, but uris can get unescaped twice
  194. const char* pos = path.BeginReading();
  195. const char* end = path.EndReading();
  196. if (*pos == '/' || *pos == ' ') {
  197. return NS_ERROR_DOM_BAD_URI;
  198. }
  199. while (pos < end) {
  200. switch (*pos) {
  201. case ':':
  202. return NS_ERROR_DOM_BAD_URI;
  203. case '.':
  204. // prevent directory traversals ("..")
  205. if (pos[1] == '.')
  206. return NS_ERROR_DOM_BAD_URI;
  207. break;
  208. case '%':
  209. // chrome: URIs with double-escapes are trying to trick us.
  210. // watch for %2e, and %25 in case someone triple unescapes
  211. if (pos[1] == '2' &&
  212. ( pos[2] == 'e' || pos[2] == 'E' ||
  213. pos[2] == '5' ))
  214. return NS_ERROR_DOM_BAD_URI;
  215. break;
  216. case '?':
  217. case '#':
  218. pos = end;
  219. continue;
  220. }
  221. ++pos;
  222. }
  223. }
  224. return NS_OK;
  225. }
  226. NS_IMETHODIMP
  227. nsChromeRegistry::ConvertChromeURL(nsIURI* aChromeURI, nsIURI* *aResult)
  228. {
  229. nsresult rv;
  230. if (NS_WARN_IF(!aChromeURI)) {
  231. return NS_ERROR_INVALID_ARG;
  232. }
  233. if (mOverrideTable.Get(aChromeURI, aResult))
  234. return NS_OK;
  235. nsCOMPtr<nsIURL> chromeURL (do_QueryInterface(aChromeURI));
  236. NS_ENSURE_TRUE(chromeURL, NS_NOINTERFACE);
  237. nsAutoCString package, provider, path;
  238. rv = chromeURL->GetHostPort(package);
  239. NS_ENSURE_SUCCESS(rv, rv);
  240. rv = GetProviderAndPath(chromeURL, provider, path);
  241. NS_ENSURE_SUCCESS(rv, rv);
  242. nsIURI* baseURI = GetBaseURIFromPackage(package, provider, path);
  243. uint32_t flags;
  244. rv = GetFlagsFromPackage(package, &flags);
  245. if (NS_FAILED(rv))
  246. return rv;
  247. if (flags & PLATFORM_PACKAGE) {
  248. #if defined(XP_WIN)
  249. path.Insert("win/", 0);
  250. #else
  251. path.Insert("unix/", 0);
  252. #endif
  253. }
  254. if (!baseURI) {
  255. LogMessage("No chrome package registered for chrome://%s/%s/%s",
  256. package.get(), provider.get(), path.get());
  257. return NS_ERROR_FILE_NOT_FOUND;
  258. }
  259. return NS_NewURI(aResult, path, nullptr, baseURI);
  260. }
  261. ////////////////////////////////////////////////////////////////////////
  262. // theme stuff
  263. static void FlushSkinBindingsForWindow(nsPIDOMWindowOuter* aWindow)
  264. {
  265. // Get the document.
  266. nsCOMPtr<nsIDocument> document = aWindow->GetDoc();
  267. if (!document)
  268. return;
  269. // Annihilate all XBL bindings.
  270. document->FlushSkinBindings();
  271. }
  272. // XXXbsmedberg: move this to nsIWindowMediator
  273. NS_IMETHODIMP nsChromeRegistry::RefreshSkins()
  274. {
  275. nsCOMPtr<nsIWindowMediator> windowMediator
  276. (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
  277. if (!windowMediator)
  278. return NS_OK;
  279. nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
  280. windowMediator->GetEnumerator(nullptr, getter_AddRefs(windowEnumerator));
  281. bool more;
  282. windowEnumerator->HasMoreElements(&more);
  283. while (more) {
  284. nsCOMPtr<nsISupports> protoWindow;
  285. windowEnumerator->GetNext(getter_AddRefs(protoWindow));
  286. if (protoWindow) {
  287. nsCOMPtr<nsPIDOMWindowOuter> domWindow = do_QueryInterface(protoWindow);
  288. if (domWindow)
  289. FlushSkinBindingsForWindow(domWindow);
  290. }
  291. windowEnumerator->HasMoreElements(&more);
  292. }
  293. FlushSkinCaches();
  294. windowMediator->GetEnumerator(nullptr, getter_AddRefs(windowEnumerator));
  295. windowEnumerator->HasMoreElements(&more);
  296. while (more) {
  297. nsCOMPtr<nsISupports> protoWindow;
  298. windowEnumerator->GetNext(getter_AddRefs(protoWindow));
  299. if (protoWindow) {
  300. nsCOMPtr<nsPIDOMWindowOuter> domWindow = do_QueryInterface(protoWindow);
  301. if (domWindow)
  302. RefreshWindow(domWindow);
  303. }
  304. windowEnumerator->HasMoreElements(&more);
  305. }
  306. return NS_OK;
  307. }
  308. void
  309. nsChromeRegistry::FlushSkinCaches()
  310. {
  311. nsCOMPtr<nsIObserverService> obsSvc =
  312. mozilla::services::GetObserverService();
  313. NS_ASSERTION(obsSvc, "Couldn't get observer service.");
  314. obsSvc->NotifyObservers(static_cast<nsIChromeRegistry*>(this),
  315. NS_CHROME_FLUSH_SKINS_TOPIC, nullptr);
  316. }
  317. // XXXbsmedberg: move this to windowmediator
  318. nsresult nsChromeRegistry::RefreshWindow(nsPIDOMWindowOuter* aWindow)
  319. {
  320. // Deal with our subframes first.
  321. nsCOMPtr<nsIDOMWindowCollection> frames = aWindow->GetFrames();
  322. uint32_t length;
  323. frames->GetLength(&length);
  324. uint32_t j;
  325. for (j = 0; j < length; j++) {
  326. nsCOMPtr<mozIDOMWindowProxy> childWin;
  327. frames->Item(j, getter_AddRefs(childWin));
  328. nsCOMPtr<nsPIDOMWindowOuter> piWindow = nsPIDOMWindowOuter::From(childWin);
  329. RefreshWindow(piWindow);
  330. }
  331. nsresult rv;
  332. // Get the document.
  333. nsCOMPtr<nsIDocument> document = aWindow->GetDoc();
  334. if (!document)
  335. return NS_OK;
  336. // Deal with the agent sheets first. Have to do all the style sets by hand.
  337. nsCOMPtr<nsIPresShell> shell = document->GetShell();
  338. if (shell) {
  339. // Reload only the chrome URL agent style sheets.
  340. nsTArray<RefPtr<StyleSheet>> agentSheets;
  341. rv = shell->GetAgentStyleSheets(agentSheets);
  342. NS_ENSURE_SUCCESS(rv, rv);
  343. nsTArray<RefPtr<StyleSheet>> newAgentSheets;
  344. for (StyleSheet* sheet : agentSheets) {
  345. nsIURI* uri = sheet->GetSheetURI();
  346. if (IsChromeURI(uri)) {
  347. // Reload the sheet.
  348. RefPtr<StyleSheet> newSheet;
  349. rv = document->LoadChromeSheetSync(uri, true, &newSheet);
  350. if (NS_FAILED(rv)) return rv;
  351. if (newSheet) {
  352. rv = newAgentSheets.AppendElement(newSheet) ? NS_OK : NS_ERROR_FAILURE;
  353. if (NS_FAILED(rv)) return rv;
  354. }
  355. }
  356. else { // Just use the same sheet.
  357. rv = newAgentSheets.AppendElement(sheet) ? NS_OK : NS_ERROR_FAILURE;
  358. if (NS_FAILED(rv)) return rv;
  359. }
  360. }
  361. rv = shell->SetAgentStyleSheets(newAgentSheets);
  362. NS_ENSURE_SUCCESS(rv, rv);
  363. }
  364. size_t count = document->SheetCount();
  365. // Build an array of style sheets we need to reload.
  366. nsTArray<RefPtr<StyleSheet>> oldSheets(count);
  367. nsTArray<RefPtr<StyleSheet>> newSheets(count);
  368. // Iterate over the style sheets.
  369. for (size_t i = 0; i < count; i++) {
  370. // Get the style sheet
  371. oldSheets.AppendElement(document->SheetAt(i));
  372. }
  373. // Iterate over our old sheets and kick off a sync load of the new
  374. // sheet if and only if it's a non-inline sheet with a chrome URL.
  375. for (StyleSheet* sheet : oldSheets) {
  376. MOZ_ASSERT(sheet, "SheetAt shouldn't return nullptr for "
  377. "in-range sheet indexes");
  378. nsIURI* uri = sheet->GetSheetURI();
  379. if (!sheet->IsInline() && IsChromeURI(uri)) {
  380. // Reload the sheet.
  381. RefPtr<StyleSheet> newSheet;
  382. // XXX what about chrome sheets that have a title or are disabled? This
  383. // only works by sheer dumb luck.
  384. document->LoadChromeSheetSync(uri, false, &newSheet);
  385. // Even if it's null, we put in in there.
  386. newSheets.AppendElement(newSheet);
  387. } else {
  388. // Just use the same sheet.
  389. newSheets.AppendElement(sheet);
  390. }
  391. }
  392. // Now notify the document that multiple sheets have been added and removed.
  393. document->UpdateStyleSheets(oldSheets, newSheets);
  394. return NS_OK;
  395. }
  396. void
  397. nsChromeRegistry::FlushAllCaches()
  398. {
  399. nsCOMPtr<nsIObserverService> obsSvc =
  400. mozilla::services::GetObserverService();
  401. NS_ASSERTION(obsSvc, "Couldn't get observer service.");
  402. obsSvc->NotifyObservers((nsIChromeRegistry*) this,
  403. NS_CHROME_FLUSH_TOPIC, nullptr);
  404. }
  405. // xxxbsmedberg Move me to nsIWindowMediator
  406. NS_IMETHODIMP
  407. nsChromeRegistry::ReloadChrome()
  408. {
  409. UpdateSelectedLocale();
  410. FlushAllCaches();
  411. // Do a reload of all top level windows.
  412. nsresult rv = NS_OK;
  413. // Get the window mediator
  414. nsCOMPtr<nsIWindowMediator> windowMediator
  415. (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
  416. if (windowMediator) {
  417. nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
  418. rv = windowMediator->GetEnumerator(nullptr, getter_AddRefs(windowEnumerator));
  419. if (NS_SUCCEEDED(rv)) {
  420. // Get each dom window
  421. bool more;
  422. rv = windowEnumerator->HasMoreElements(&more);
  423. if (NS_FAILED(rv)) return rv;
  424. while (more) {
  425. nsCOMPtr<nsISupports> protoWindow;
  426. rv = windowEnumerator->GetNext(getter_AddRefs(protoWindow));
  427. if (NS_SUCCEEDED(rv)) {
  428. nsCOMPtr<nsPIDOMWindowOuter> domWindow = do_QueryInterface(protoWindow);
  429. if (domWindow) {
  430. nsIDOMLocation* location = domWindow->GetLocation();
  431. if (location) {
  432. rv = location->Reload(false);
  433. if (NS_FAILED(rv)) return rv;
  434. }
  435. }
  436. }
  437. rv = windowEnumerator->HasMoreElements(&more);
  438. if (NS_FAILED(rv)) return rv;
  439. }
  440. }
  441. }
  442. return rv;
  443. }
  444. NS_IMETHODIMP
  445. nsChromeRegistry::AllowScriptsForPackage(nsIURI* aChromeURI, bool *aResult)
  446. {
  447. nsresult rv;
  448. *aResult = false;
  449. #ifdef DEBUG
  450. bool isChrome;
  451. aChromeURI->SchemeIs("chrome", &isChrome);
  452. NS_ASSERTION(isChrome, "Non-chrome URI passed to AllowScriptsForPackage!");
  453. #endif
  454. nsCOMPtr<nsIURL> url (do_QueryInterface(aChromeURI));
  455. NS_ENSURE_TRUE(url, NS_NOINTERFACE);
  456. nsAutoCString provider, file;
  457. rv = GetProviderAndPath(url, provider, file);
  458. NS_ENSURE_SUCCESS(rv, rv);
  459. if (!provider.EqualsLiteral("skin"))
  460. *aResult = true;
  461. return NS_OK;
  462. }
  463. NS_IMETHODIMP
  464. nsChromeRegistry::AllowContentToAccess(nsIURI *aURI, bool *aResult)
  465. {
  466. nsresult rv;
  467. *aResult = false;
  468. #ifdef DEBUG
  469. bool isChrome;
  470. aURI->SchemeIs("chrome", &isChrome);
  471. NS_ASSERTION(isChrome, "Non-chrome URI passed to AllowContentToAccess!");
  472. #endif
  473. nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
  474. if (!url) {
  475. NS_ERROR("Chrome URL doesn't implement nsIURL.");
  476. return NS_ERROR_UNEXPECTED;
  477. }
  478. nsAutoCString package;
  479. rv = url->GetHostPort(package);
  480. NS_ENSURE_SUCCESS(rv, rv);
  481. uint32_t flags;
  482. rv = GetFlagsFromPackage(package, &flags);
  483. if (NS_SUCCEEDED(rv)) {
  484. *aResult = !!(flags & CONTENT_ACCESSIBLE);
  485. }
  486. return NS_OK;
  487. }
  488. NS_IMETHODIMP
  489. nsChromeRegistry::CanLoadURLRemotely(nsIURI *aURI, bool *aResult)
  490. {
  491. nsresult rv;
  492. *aResult = false;
  493. #ifdef DEBUG
  494. bool isChrome;
  495. aURI->SchemeIs("chrome", &isChrome);
  496. NS_ASSERTION(isChrome, "Non-chrome URI passed to CanLoadURLRemotely!");
  497. #endif
  498. nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
  499. if (!url) {
  500. NS_ERROR("Chrome URL doesn't implement nsIURL.");
  501. return NS_ERROR_UNEXPECTED;
  502. }
  503. nsAutoCString package;
  504. rv = url->GetHostPort(package);
  505. NS_ENSURE_SUCCESS(rv, rv);
  506. uint32_t flags;
  507. rv = GetFlagsFromPackage(package, &flags);
  508. if (NS_SUCCEEDED(rv)) {
  509. *aResult = !!(flags & REMOTE_ALLOWED);
  510. }
  511. return NS_OK;
  512. }
  513. NS_IMETHODIMP
  514. nsChromeRegistry::MustLoadURLRemotely(nsIURI *aURI, bool *aResult)
  515. {
  516. nsresult rv;
  517. *aResult = false;
  518. #ifdef DEBUG
  519. bool isChrome;
  520. aURI->SchemeIs("chrome", &isChrome);
  521. NS_ASSERTION(isChrome, "Non-chrome URI passed to MustLoadURLRemotely!");
  522. #endif
  523. nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
  524. if (!url) {
  525. NS_ERROR("Chrome URL doesn't implement nsIURL.");
  526. return NS_ERROR_UNEXPECTED;
  527. }
  528. nsAutoCString package;
  529. rv = url->GetHostPort(package);
  530. NS_ENSURE_SUCCESS(rv, rv);
  531. uint32_t flags;
  532. rv = GetFlagsFromPackage(package, &flags);
  533. if (NS_SUCCEEDED(rv)) {
  534. *aResult = !!(flags & REMOTE_REQUIRED);
  535. }
  536. return NS_OK;
  537. }
  538. bool
  539. nsChromeRegistry::GetDirectionForLocale(const nsACString& aLocale)
  540. {
  541. // first check the intl.uidirection.<locale> preference, and if that is not
  542. // set, check the same preference but with just the first two characters of
  543. // the locale. If that isn't set, default to left-to-right.
  544. nsAutoCString prefString = NS_LITERAL_CSTRING("intl.uidirection.") + aLocale;
  545. nsCOMPtr<nsIPrefBranch> prefBranch (do_GetService(NS_PREFSERVICE_CONTRACTID));
  546. if (!prefBranch) {
  547. return false;
  548. }
  549. nsXPIDLCString dir;
  550. prefBranch->GetCharPref(prefString.get(), getter_Copies(dir));
  551. if (dir.IsEmpty()) {
  552. int32_t hyphen = prefString.FindChar('-');
  553. if (hyphen >= 1) {
  554. nsAutoCString shortPref(Substring(prefString, 0, hyphen));
  555. prefBranch->GetCharPref(shortPref.get(), getter_Copies(dir));
  556. }
  557. }
  558. return dir.EqualsLiteral("rtl");
  559. }
  560. NS_IMETHODIMP_(bool)
  561. nsChromeRegistry::WrappersEnabled(nsIURI *aURI)
  562. {
  563. nsCOMPtr<nsIURL> chromeURL (do_QueryInterface(aURI));
  564. if (!chromeURL)
  565. return false;
  566. bool isChrome = false;
  567. nsresult rv = chromeURL->SchemeIs("chrome", &isChrome);
  568. if (NS_FAILED(rv) || !isChrome)
  569. return false;
  570. nsAutoCString package;
  571. rv = chromeURL->GetHostPort(package);
  572. if (NS_FAILED(rv))
  573. return false;
  574. uint32_t flags;
  575. rv = GetFlagsFromPackage(package, &flags);
  576. return NS_SUCCEEDED(rv) && (flags & XPCNATIVEWRAPPERS);
  577. }
  578. already_AddRefed<nsChromeRegistry>
  579. nsChromeRegistry::GetSingleton()
  580. {
  581. if (gChromeRegistry) {
  582. RefPtr<nsChromeRegistry> registry = gChromeRegistry;
  583. return registry.forget();
  584. }
  585. RefPtr<nsChromeRegistry> cr;
  586. if (GeckoProcessType_Content == XRE_GetProcessType())
  587. cr = new nsChromeRegistryContent();
  588. else
  589. cr = new nsChromeRegistryChrome();
  590. if (NS_FAILED(cr->Init()))
  591. return nullptr;
  592. return cr.forget();
  593. }
  594. void
  595. nsChromeRegistry::SanitizeForBCP47(nsACString& aLocale)
  596. {
  597. // Currently, the only locale code we use that's not BCP47-conformant is
  598. // "ja-JP-mac" on OS X, but let's try to be more general than just
  599. // hard-coding that here.
  600. const int32_t LANG_TAG_CAPACITY = 128;
  601. char langTag[LANG_TAG_CAPACITY];
  602. nsAutoCString locale(aLocale);
  603. UErrorCode err = U_ZERO_ERROR;
  604. // This is a fail-safe method that will set langTag to "und" if it cannot
  605. // match any part of the input locale code.
  606. int32_t len = uloc_toLanguageTag(locale.get(), langTag, LANG_TAG_CAPACITY,
  607. false, &err);
  608. if (U_SUCCESS(err) && len > 0) {
  609. aLocale.Assign(langTag, len);
  610. }
  611. }