Coverage Report

Created: 2018-09-25 14:53

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