Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/chrome/nsChromeRegistryChrome.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=2 sts=2 sw=2 et tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "mozilla/dom/ContentParent.h"
8
#include "RegistryMessageUtils.h"
9
#include "nsResProtocolHandler.h"
10
11
#include "nsChromeRegistryChrome.h"
12
13
#if defined(XP_WIN)
14
#include <windows.h>
15
#elif defined(XP_MACOSX)
16
#include <CoreServices/CoreServices.h>
17
#endif
18
19
#include "nsArrayEnumerator.h"
20
#include "nsComponentManager.h"
21
#include "nsEnumeratorUtils.h"
22
#include "nsNetUtil.h"
23
#include "nsStringEnumerator.h"
24
#include "nsTextFormatter.h"
25
#include "nsXPCOMCIDInternal.h"
26
27
#include "mozilla/LookAndFeel.h"
28
#include "mozilla/Unused.h"
29
#include "mozilla/intl/LocaleService.h"
30
31
#include "nsIObserverService.h"
32
#include "nsIPrefBranch.h"
33
#include "nsIPrefService.h"
34
#include "mozilla/Preferences.h"
35
#include "nsIResProtocolHandler.h"
36
#include "nsIScriptError.h"
37
#include "nsIXULRuntime.h"
38
39
6
#define SELECTED_SKIN_PREF   "general.skins.selectedSkin"
40
#define PACKAGE_OVERRIDE_BRANCH "chrome.override_package."
41
42
using namespace mozilla;
43
using mozilla::dom::ContentParent;
44
using mozilla::dom::PContentParent;
45
using mozilla::intl::LocaleService;
46
47
// We use a "best-fit" algorithm for matching locales and themes.
48
// 1) the exact selected locale/theme
49
// 2) (locales only) same language, different country
50
//    e.g. en-GB is the selected locale, only en-US is available
51
// 3) any available locale/theme
52
53
/**
54
 * Match the language-part of two lang-COUNTRY codes, hopefully but
55
 * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also
56
 * work, any other garbage-in will produce undefined results as long
57
 * as it does not crash.
58
 */
59
static bool
60
LanguagesMatch(const nsACString& a, const nsACString& b)
61
0
{
62
0
  if (a.Length() < 2 || b.Length() < 2)
63
0
    return false;
64
0
65
0
  nsACString::const_iterator as, ae, bs, be;
66
0
  a.BeginReading(as);
67
0
  a.EndReading(ae);
68
0
  b.BeginReading(bs);
69
0
  b.EndReading(be);
70
0
71
0
  while (*as == *bs) {
72
0
    if (*as == '-')
73
0
      return true;
74
0
75
0
    ++as; ++bs;
76
0
77
0
    // reached the end
78
0
    if (as == ae && bs == be)
79
0
      return true;
80
0
81
0
    // "a" is short
82
0
    if (as == ae)
83
0
      return (*bs == '-');
84
0
85
0
    // "b" is short
86
0
    if (bs == be)
87
0
      return (*as == '-');
88
0
  }
89
0
90
0
  return false;
91
0
}
92
93
nsChromeRegistryChrome::nsChromeRegistryChrome()
94
  : mProfileLoaded(false)
95
  , mDynamicRegistration(true)
96
3
{
97
3
}
98
99
nsChromeRegistryChrome::~nsChromeRegistryChrome()
100
0
{
101
0
}
102
103
nsresult
104
nsChromeRegistryChrome::Init()
105
3
{
106
3
  nsresult rv = nsChromeRegistry::Init();
107
3
  if (NS_FAILED(rv))
108
3
    return rv;
109
3
110
3
  mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0");
111
3
112
3
  bool safeMode = false;
113
3
  nsCOMPtr<nsIXULRuntime> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
114
3
  if (xulrun)
115
3
    xulrun->GetInSafeMode(&safeMode);
116
3
117
3
  nsCOMPtr<nsIPrefService> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID));
118
3
  nsCOMPtr<nsIPrefBranch> prefs;
119
3
120
3
  if (prefserv) {
121
3
    if (safeMode) {
122
0
      prefserv->GetDefaultBranch(nullptr, getter_AddRefs(prefs));
123
3
    } else {
124
3
      prefs = do_QueryInterface(prefserv);
125
3
    }
126
3
  }
127
3
128
3
  if (!prefs) {
129
0
    NS_WARNING("Could not get pref service!");
130
3
  } else {
131
3
    nsAutoCString provider;
132
3
    rv = prefs->GetCharPref(SELECTED_SKIN_PREF, provider);
133
3
    if (NS_SUCCEEDED(rv))
134
3
      mSelectedSkin = provider;
135
3
136
3
    rv = prefs->AddObserver(SELECTED_SKIN_PREF, this, true);
137
3
  }
138
3
139
3
  nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
140
3
  if (obsService) {
141
3
    obsService->AddObserver(this, "profile-initial-state", true);
142
3
    obsService->AddObserver(this, "intl:app-locales-changed", true);
143
3
  }
144
3
145
3
  return NS_OK;
146
3
}
147
148
NS_IMETHODIMP
149
nsChromeRegistryChrome::CheckForOSAccessibility()
150
0
{
151
0
  int32_t useAccessibilityTheme =
152
0
    LookAndFeel::GetInt(LookAndFeel::eIntID_UseAccessibilityTheme, 0);
153
0
154
0
  if (useAccessibilityTheme) {
155
0
    /* Set the skin to classic and remove pref observers */
156
0
    if (!mSelectedSkin.EqualsLiteral("classic/1.0")) {
157
0
      mSelectedSkin.AssignLiteral("classic/1.0");
158
0
      RefreshSkins();
159
0
    }
160
0
161
0
    nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
162
0
    if (prefs) {
163
0
      prefs->RemoveObserver(SELECTED_SKIN_PREF, this);
164
0
    }
165
0
  }
166
0
167
0
  return NS_OK;
168
0
}
169
170
NS_IMETHODIMP
171
nsChromeRegistryChrome::GetLocalesForPackage(const nsACString& aPackage,
172
                                       nsIUTF8StringEnumerator* *aResult)
173
0
{
174
0
  nsCString realpackage;
175
0
  nsresult rv = OverrideLocalePackage(aPackage, realpackage);
176
0
  if (NS_FAILED(rv))
177
0
    return rv;
178
0
179
0
  nsTArray<nsCString> *a = new nsTArray<nsCString>;
180
0
  if (!a)
181
0
    return NS_ERROR_OUT_OF_MEMORY;
182
0
183
0
  PackageEntry* entry;
184
0
  if (mPackagesHash.Get(realpackage, &entry)) {
185
0
    entry->locales.EnumerateToArray(a);
186
0
  }
187
0
188
0
  rv = NS_NewAdoptingUTF8StringEnumerator(aResult, a);
189
0
  if (NS_FAILED(rv))
190
0
    delete a;
191
0
192
0
  return rv;
193
0
}
194
195
NS_IMETHODIMP
196
nsChromeRegistryChrome::IsLocaleRTL(const nsACString& package, bool *aResult)
197
0
{
198
0
  *aResult = false;
199
0
200
0
  nsAutoCString locale;
201
0
  GetSelectedLocale(package, false, locale);
202
0
  if (locale.Length() < 2)
203
0
    return NS_OK;
204
0
205
0
  *aResult = GetDirectionForLocale(locale);
206
0
  return NS_OK;
207
0
}
208
209
/**
210
 * This method negotiates only between the app locale and the available
211
 * chrome packages.
212
 *
213
 * If you want to get the current application's UI locale, please use
214
 * LocaleService::GetAppLocaleAsLangTag.
215
 */
216
nsresult
217
nsChromeRegistryChrome::GetSelectedLocale(const nsACString& aPackage,
218
                                          bool aAsBCP47,
219
                                          nsACString& aLocale)
220
0
{
221
0
  nsAutoCString reqLocale;
222
0
  if (aPackage.EqualsLiteral("global")) {
223
0
    LocaleService::GetInstance()->GetAppLocaleAsLangTag(reqLocale);
224
0
  } else {
225
0
    AutoTArray<nsCString, 10> requestedLocales;
226
0
    LocaleService::GetInstance()->GetRequestedLocales(requestedLocales);
227
0
    reqLocale.Assign(requestedLocales[0]);
228
0
  }
229
0
230
0
  nsCString realpackage;
231
0
  nsresult rv = OverrideLocalePackage(aPackage, realpackage);
232
0
  if (NS_FAILED(rv))
233
0
    return rv;
234
0
  PackageEntry* entry;
235
0
  if (!mPackagesHash.Get(realpackage, &entry))
236
0
    return NS_ERROR_FILE_NOT_FOUND;
237
0
238
0
  aLocale = entry->locales.GetSelected(reqLocale, nsProviderArray::LOCALE);
239
0
  if (aLocale.IsEmpty())
240
0
    return NS_ERROR_FAILURE;
241
0
242
0
  if (aAsBCP47) {
243
0
    SanitizeForBCP47(aLocale);
244
0
  }
245
0
246
0
  return NS_OK;
247
0
}
248
249
nsresult
250
nsChromeRegistryChrome::OverrideLocalePackage(const nsACString& aPackage,
251
                                              nsACString& aOverride)
252
36
{
253
36
  const nsACString& pref = NS_LITERAL_CSTRING(PACKAGE_OVERRIDE_BRANCH) + aPackage;
254
36
  nsAutoCString override;
255
36
  nsresult rv =
256
36
    mozilla::Preferences::GetCString(PromiseFlatCString(pref).get(), override);
257
36
  if (NS_SUCCEEDED(rv)) {
258
0
    aOverride = override;
259
36
  } else {
260
36
    aOverride = aPackage;
261
36
  }
262
36
  return NS_OK;
263
36
}
264
265
NS_IMETHODIMP
266
nsChromeRegistryChrome::Observe(nsISupports *aSubject, const char *aTopic,
267
                                const char16_t *someData)
268
0
{
269
0
  nsresult rv = NS_OK;
270
0
271
0
  if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
272
0
    nsCOMPtr<nsIPrefBranch> prefs (do_QueryInterface(aSubject));
273
0
    NS_ASSERTION(prefs, "Bad observer call!");
274
0
275
0
    NS_ConvertUTF16toUTF8 pref(someData);
276
0
277
0
    if (pref.EqualsLiteral(SELECTED_SKIN_PREF)) {
278
0
      nsAutoCString provider;
279
0
      rv = prefs->GetCharPref(pref.get(), provider);
280
0
      if (NS_FAILED(rv)) {
281
0
        NS_ERROR("Couldn't get new skin pref!");
282
0
        return rv;
283
0
      }
284
0
285
0
      mSelectedSkin = provider;
286
0
      RefreshSkins();
287
0
    } else {
288
0
      NS_ERROR("Unexpected pref!");
289
0
    }
290
0
  }
291
0
  else if (!strcmp("profile-initial-state", aTopic)) {
292
0
    mProfileLoaded = true;
293
0
  }
294
0
  else if (!strcmp("intl:app-locales-changed", aTopic)) {
295
0
    if (mProfileLoaded) {
296
0
      FlushAllCaches();
297
0
    }
298
0
  }
299
0
  else {
300
0
    NS_ERROR("Unexpected observer topic!");
301
0
  }
302
0
303
0
  return rv;
304
0
}
305
306
NS_IMETHODIMP
307
nsChromeRegistryChrome::CheckForNewChrome()
308
0
{
309
0
  mPackagesHash.Clear();
310
0
  mOverrideTable.Clear();
311
0
312
0
  mDynamicRegistration = false;
313
0
314
0
  nsComponentManagerImpl::gComponentManager->RereadChromeManifests();
315
0
316
0
  mDynamicRegistration = true;
317
0
318
0
  SendRegisteredChrome(nullptr);
319
0
  return NS_OK;
320
0
}
321
322
static void
323
SerializeURI(nsIURI* aURI,
324
             SerializedURI& aSerializedURI)
325
273
{
326
273
  if (!aURI)
327
123
    return;
328
150
329
150
  aURI->GetSpec(aSerializedURI.spec);
330
150
}
331
332
void
333
nsChromeRegistryChrome::SendRegisteredChrome(
334
    mozilla::dom::PContentParent* aParent)
335
0
{
336
0
  InfallibleTArray<ChromePackage> packages;
337
0
  InfallibleTArray<SubstitutionMapping> resources;
338
0
  InfallibleTArray<OverrideMapping> overrides;
339
0
340
0
  for (auto iter = mPackagesHash.Iter(); !iter.Done(); iter.Next()) {
341
0
    ChromePackage chromePackage;
342
0
    ChromePackageFromPackageEntry(iter.Key(), iter.UserData(), &chromePackage,
343
0
                                  mSelectedSkin);
344
0
    packages.AppendElement(chromePackage);
345
0
  }
346
0
347
0
  // If we were passed a parent then a new child process has been created and
348
0
  // has requested all of the chrome so send it the resources too. Otherwise
349
0
  // resource mappings are sent by the resource protocol handler dynamically.
350
0
  if (aParent) {
351
0
    nsCOMPtr<nsIIOService> io (do_GetIOService());
352
0
    NS_ENSURE_TRUE_VOID(io);
353
0
354
0
    nsCOMPtr<nsIProtocolHandler> ph;
355
0
    nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
356
0
    NS_ENSURE_SUCCESS_VOID(rv);
357
0
358
0
    nsCOMPtr<nsIResProtocolHandler> irph (do_QueryInterface(ph));
359
0
    nsResProtocolHandler* rph = static_cast<nsResProtocolHandler*>(irph.get());
360
0
    rv = rph->CollectSubstitutions(resources);
361
0
    NS_ENSURE_SUCCESS_VOID(rv);
362
0
  }
363
0
364
0
  for (auto iter = mOverrideTable.Iter(); !iter.Done(); iter.Next()) {
365
0
    SerializedURI chromeURI, overrideURI;
366
0
367
0
    SerializeURI(iter.Key(), chromeURI);
368
0
    SerializeURI(iter.UserData(), overrideURI);
369
0
370
0
    OverrideMapping override = { chromeURI, overrideURI };
371
0
    overrides.AppendElement(override);
372
0
  }
373
0
374
0
  nsAutoCString appLocale;
375
0
  LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
376
0
377
0
  if (aParent) {
378
0
    bool success = aParent->SendRegisterChrome(packages, resources, overrides,
379
0
                                               appLocale, false);
380
0
    NS_ENSURE_TRUE_VOID(success);
381
0
  } else {
382
0
    nsTArray<ContentParent*> parents;
383
0
    ContentParent::GetAll(parents);
384
0
    if (!parents.Length())
385
0
      return;
386
0
387
0
    for (uint32_t i = 0; i < parents.Length(); i++) {
388
0
      DebugOnly<bool> success =
389
0
        parents[i]->SendRegisterChrome(packages, resources, overrides,
390
0
                                       appLocale, true);
391
0
      NS_WARNING_ASSERTION(success,
392
0
                           "couldn't reset a child's registered chrome");
393
0
    }
394
0
  }
395
0
}
396
397
/* static */ void
398
nsChromeRegistryChrome::ChromePackageFromPackageEntry(const nsACString& aPackageName,
399
                                                      PackageEntry* aPackage,
400
                                                      ChromePackage* aChromePackage,
401
                                                      const nsCString& aSelectedSkin)
402
75
{
403
75
  nsAutoCString appLocale;
404
75
  LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
405
75
406
75
  SerializeURI(aPackage->baseURI, aChromePackage->contentBaseURI);
407
75
  SerializeURI(aPackage->locales.GetBase(appLocale, nsProviderArray::LOCALE),
408
75
               aChromePackage->localeBaseURI);
409
75
  SerializeURI(aPackage->skins.GetBase(aSelectedSkin, nsProviderArray::ANY),
410
75
               aChromePackage->skinBaseURI);
411
75
  aChromePackage->package = aPackageName;
412
75
  aChromePackage->flags = aPackage->flags;
413
75
}
414
415
static bool
416
CanLoadResource(nsIURI* aResourceURI)
417
129
{
418
129
  bool isLocalResource = false;
419
129
  (void)NS_URIChainHasFlags(aResourceURI,
420
129
                            nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
421
129
                            &isLocalResource);
422
129
  return isLocalResource;
423
129
}
424
425
nsIURI*
426
nsChromeRegistryChrome::GetBaseURIFromPackage(const nsCString& aPackage,
427
                                              const nsCString& aProvider,
428
                                              const nsCString& aPath)
429
0
{
430
0
  PackageEntry* entry;
431
0
  if (!mPackagesHash.Get(aPackage, &entry)) {
432
0
    if (!mInitialized)
433
0
      return nullptr;
434
0
435
0
    LogMessage("No chrome package registered for chrome://%s/%s/%s",
436
0
               aPackage.get(), aProvider.get(), aPath.get());
437
0
438
0
    return nullptr;
439
0
  }
440
0
441
0
  if (aProvider.EqualsLiteral("locale")) {
442
0
    nsAutoCString appLocale;
443
0
    LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
444
0
    return entry->locales.GetBase(appLocale, nsProviderArray::LOCALE);
445
0
  }
446
0
  else if (aProvider.EqualsLiteral("skin")) {
447
0
    return entry->skins.GetBase(mSelectedSkin, nsProviderArray::ANY);
448
0
  }
449
0
  else if (aProvider.EqualsLiteral("content")) {
450
0
    return entry->baseURI;
451
0
  }
452
0
  return nullptr;
453
0
}
454
455
nsresult
456
nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString& aPackage,
457
                                            uint32_t* aFlags)
458
0
{
459
0
  PackageEntry* entry;
460
0
  if (!mPackagesHash.Get(aPackage, &entry))
461
0
    return NS_ERROR_FILE_NOT_FOUND;
462
0
463
0
  *aFlags = entry->flags;
464
0
  return NS_OK;
465
0
}
466
467
nsChromeRegistryChrome::ProviderEntry*
468
nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType)
469
195
{
470
195
  size_t i = mArray.Length();
471
195
  if (!i)
472
144
    return nullptr;
473
51
474
51
  ProviderEntry* found = nullptr;  // Only set if we find a partial-match locale
475
51
  ProviderEntry* entry = nullptr;
476
51
477
51
  while (i--) {
478
51
    entry = &mArray[i];
479
51
    if (aPreferred.Equals(entry->provider))
480
51
      return entry;
481
0
482
0
    if (aType != LOCALE)
483
0
      continue;
484
0
485
0
    if (LanguagesMatch(aPreferred, entry->provider)) {
486
0
      found = entry;
487
0
      continue;
488
0
    }
489
0
490
0
    if (!found && entry->provider.EqualsLiteral("en-US"))
491
0
      found = entry;
492
0
  }
493
51
494
51
  if (!found && aType != EXACT)
495
0
    return entry;
496
0
497
0
  return found;
498
0
}
499
500
nsIURI*
501
nsChromeRegistryChrome::nsProviderArray::GetBase(const nsACString& aPreferred, MatchType aType)
502
150
{
503
150
  ProviderEntry* provider = GetProvider(aPreferred, aType);
504
150
505
150
  if (!provider)
506
99
    return nullptr;
507
51
508
51
  return provider->baseURI;
509
51
}
510
511
const nsACString&
512
nsChromeRegistryChrome::nsProviderArray::GetSelected(const nsACString& aPreferred, MatchType aType)
513
0
{
514
0
  ProviderEntry* entry = GetProvider(aPreferred, aType);
515
0
516
0
  if (entry)
517
0
    return entry->provider;
518
0
519
0
  return EmptyCString();
520
0
}
521
522
void
523
nsChromeRegistryChrome::nsProviderArray::SetBase(const nsACString& aProvider, nsIURI* aBaseURL)
524
45
{
525
45
  ProviderEntry* provider = GetProvider(aProvider, EXACT);
526
45
527
45
  if (provider) {
528
0
    provider->baseURI = aBaseURL;
529
0
    return;
530
0
  }
531
45
532
45
  // no existing entries, add a new one
533
45
  mArray.AppendElement(ProviderEntry(aProvider, aBaseURL));
534
45
}
535
536
void
537
nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(nsTArray<nsCString> *a)
538
0
{
539
0
  int32_t i = mArray.Length();
540
0
  while (i--) {
541
0
    a->AppendElement(mArray[i].provider);
542
0
  }
543
0
}
544
545
nsIURI*
546
nsChromeRegistry::ManifestProcessingContext::GetManifestURI()
547
153
{
548
153
  if (!mManifestURI) {
549
6
    nsCString uri;
550
6
    mFile.GetURIString(uri);
551
6
    NS_NewURI(getter_AddRefs(mManifestURI), uri);
552
6
  }
553
153
  return mManifestURI;
554
153
}
555
556
already_AddRefed<nsIURI>
557
nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri)
558
153
{
559
153
  nsIURI* baseuri = GetManifestURI();
560
153
  if (!baseuri)
561
0
    return nullptr;
562
153
563
153
  nsCOMPtr<nsIURI> resolved;
564
153
  nsresult rv = NS_NewURI(getter_AddRefs(resolved), uri, baseuri);
565
153
  if (NS_FAILED(rv))
566
153
    return nullptr;
567
153
568
153
  return resolved.forget();
569
153
}
570
571
static void
572
EnsureLowerCase(char *aBuf)
573
105
{
574
1.14k
  for (; *aBuf; ++aBuf) {
575
1.03k
    char ch = *aBuf;
576
1.03k
    if (ch >= 'A' && ch <= 'Z')
577
0
      *aBuf = ch + 'a' - 'A';
578
1.03k
  }
579
105
}
580
581
static void
582
SendManifestEntry(const ChromeRegistryItem &aItem)
583
99
{
584
99
  nsTArray<ContentParent*> parents;
585
99
  ContentParent::GetAll(parents);
586
99
  if (!parents.Length())
587
99
    return;
588
0
589
0
  for (uint32_t i = 0; i < parents.Length(); i++) {
590
0
    Unused << parents[i]->SendRegisterChromeItem(aItem);
591
0
  }
592
0
}
593
594
void
595
nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int lineno,
596
                                        char *const * argv, int flags)
597
30
{
598
30
  char* package = argv[0];
599
30
  char* uri = argv[1];
600
30
601
30
  EnsureLowerCase(package);
602
30
603
30
  nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
604
30
  if (!resolved) {
605
0
    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
606
0
                          "During chrome registration, unable to create URI '%s'.", uri);
607
0
    return;
608
0
  }
609
30
610
30
  if (!CanLoadResource(resolved)) {
611
0
    LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
612
0
                          "During chrome registration, cannot register non-local URI '%s' as content.",
613
0
                          uri);
614
0
    return;
615
0
  }
616
30
617
30
  nsDependentCString packageName(package);
618
30
  PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
619
30
  entry->baseURI = resolved;
620
30
  entry->flags = flags;
621
30
622
30
  if (mDynamicRegistration) {
623
30
    ChromePackage chromePackage;
624
30
    ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
625
30
                                  mSelectedSkin);
626
30
    SendManifestEntry(chromePackage);
627
30
  }
628
30
}
629
630
void
631
nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno,
632
                                       char *const * argv, int flags)
633
36
{
634
36
  char* package = argv[0];
635
36
  char* provider = argv[1];
636
36
  char* uri = argv[2];
637
36
638
36
  EnsureLowerCase(package);
639
36
640
36
  nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
641
36
  if (!resolved) {
642
0
    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
643
0
                          "During chrome registration, unable to create URI '%s'.", uri);
644
0
    return;
645
0
  }
646
36
647
36
  if (!CanLoadResource(resolved)) {
648
0
    LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
649
0
                          "During chrome registration, cannot register non-local URI '%s' as content.",
650
0
                          uri);
651
0
    return;
652
0
  }
653
36
654
36
  nsDependentCString packageName(package);
655
36
  PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
656
36
  entry->locales.SetBase(nsDependentCString(provider), resolved);
657
36
658
36
  if (mDynamicRegistration) {
659
36
    ChromePackage chromePackage;
660
36
    ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
661
36
                                  mSelectedSkin);
662
36
    SendManifestEntry(chromePackage);
663
36
  }
664
36
665
36
  // We use mainPackage as the package we track for reporting new locales being
666
36
  // registered. For most cases it will be "global", but for Fennec it will be
667
36
  // "browser".
668
36
  nsAutoCString mainPackage;
669
36
  nsresult rv = OverrideLocalePackage(NS_LITERAL_CSTRING("global"), mainPackage);
670
36
  if (NS_FAILED(rv)) {
671
0
    return;
672
0
  }
673
36
}
674
675
void
676
nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno,
677
                                     char *const * argv, int flags)
678
9
{
679
9
  char* package = argv[0];
680
9
  char* provider = argv[1];
681
9
  char* uri = argv[2];
682
9
683
9
  EnsureLowerCase(package);
684
9
685
9
  nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
686
9
  if (!resolved) {
687
0
    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
688
0
                          "During chrome registration, unable to create URI '%s'.", uri);
689
0
    return;
690
0
  }
691
9
692
9
  if (!CanLoadResource(resolved)) {
693
0
    LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
694
0
                          "During chrome registration, cannot register non-local URI '%s' as content.",
695
0
                          uri);
696
0
    return;
697
0
  }
698
9
699
9
  nsDependentCString packageName(package);
700
9
  PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
701
9
  entry->skins.SetBase(nsDependentCString(provider), resolved);
702
9
703
9
  if (mDynamicRegistration) {
704
9
    ChromePackage chromePackage;
705
9
    ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
706
9
                                  mSelectedSkin);
707
9
    SendManifestEntry(chromePackage);
708
9
  }
709
9
}
710
711
void
712
nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int lineno,
713
                                         char *const * argv, int flags)
714
24
{
715
24
  char* chrome = argv[0];
716
24
  char* resolved = argv[1];
717
24
718
24
  nsCOMPtr<nsIURI> chromeuri = cx.ResolveURI(chrome);
719
24
  nsCOMPtr<nsIURI> resolveduri = cx.ResolveURI(resolved);
720
24
  if (!chromeuri || !resolveduri) {
721
0
    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
722
0
                          "During chrome registration, unable to create URI.");
723
0
    return;
724
0
  }
725
24
726
24
  if (cx.mType == NS_SKIN_LOCATION) {
727
0
    bool chromeSkinOnly = false;
728
0
    nsresult rv = chromeuri->SchemeIs("chrome", &chromeSkinOnly);
729
0
    chromeSkinOnly = chromeSkinOnly && NS_SUCCEEDED(rv);
730
0
    if (chromeSkinOnly) {
731
0
      rv = resolveduri->SchemeIs("chrome", &chromeSkinOnly);
732
0
      chromeSkinOnly = chromeSkinOnly && NS_SUCCEEDED(rv);
733
0
    }
734
0
    if (chromeSkinOnly) {
735
0
      nsAutoCString chromePath, resolvedPath;
736
0
      chromeuri->GetPathQueryRef(chromePath);
737
0
      resolveduri->GetPathQueryRef(resolvedPath);
738
0
      chromeSkinOnly = StringBeginsWith(chromePath, NS_LITERAL_CSTRING("/skin/")) &&
739
0
                       StringBeginsWith(resolvedPath, NS_LITERAL_CSTRING("/skin/"));
740
0
    }
741
0
    if (!chromeSkinOnly) {
742
0
      LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
743
0
                            "Cannot register non-chrome://.../skin/ URIs '%s' and '%s' as overrides and/or to be overridden from a skin manifest.",
744
0
                            chrome, resolved);
745
0
      return;
746
0
    }
747
24
  }
748
24
749
24
  if (!CanLoadResource(resolveduri)) {
750
0
    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
751
0
                          "Cannot register non-local URI '%s' for an override.", resolved);
752
0
    return;
753
0
  }
754
24
  mOverrideTable.Put(chromeuri, resolveduri);
755
24
756
24
  if (mDynamicRegistration) {
757
24
    SerializedURI serializedChrome;
758
24
    SerializedURI serializedOverride;
759
24
760
24
    SerializeURI(chromeuri, serializedChrome);
761
24
    SerializeURI(resolveduri, serializedOverride);
762
24
763
24
    OverrideMapping override = { serializedChrome, serializedOverride };
764
24
    SendManifestEntry(override);
765
24
  }
766
24
}
767
768
void
769
nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx, int lineno,
770
                                         char *const * argv, int flags)
771
30
{
772
30
  char* package = argv[0];
773
30
  char* uri = argv[1];
774
30
775
30
  EnsureLowerCase(package);
776
30
  nsDependentCString host(package);
777
30
778
30
  nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
779
30
  if (!io) {
780
0
    NS_WARNING("No IO service trying to process chrome manifests");
781
0
    return;
782
0
  }
783
30
784
30
  nsCOMPtr<nsIProtocolHandler> ph;
785
30
  nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
786
30
  if (NS_FAILED(rv))
787
30
    return;
788
30
789
30
  nsCOMPtr<nsIResProtocolHandler> rph = do_QueryInterface(ph);
790
30
791
30
  nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
792
30
  if (!resolved) {
793
0
    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
794
0
                          "During chrome registration, unable to create URI '%s'.", uri);
795
0
    return;
796
0
  }
797
30
798
30
  if (!CanLoadResource(resolved)) {
799
0
    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
800
0
                          "Warning: cannot register non-local URI '%s' as a resource.",
801
0
                          uri);
802
0
    return;
803
0
  }
804
30
805
30
  // By default, Firefox resources are not content-accessible unless the
806
30
  // manifests opts in.
807
30
  bool contentAccessible = (flags & nsChromeRegistry::CONTENT_ACCESSIBLE);
808
30
809
30
  uint32_t substitutionFlags = 0;
810
30
  if (contentAccessible) {
811
9
    substitutionFlags |= nsIResProtocolHandler::ALLOW_CONTENT_ACCESS;
812
9
  }
813
30
  rv = rph->SetSubstitutionWithFlags(host, resolved, substitutionFlags);
814
30
  if (NS_FAILED(rv)) {
815
0
    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
816
0
                          "Warning: cannot set substitution for '%s'.",
817
0
                          uri);
818
0
  }
819
30
}