Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/xpcom/components/ManifestParser.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=8 sts=2 et sw=2 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/ArrayUtils.h"
8
#include "mozilla/Printf.h"
9
#include "mozilla/UniquePtr.h"
10
11
#include "ManifestParser.h"
12
13
#include <string.h>
14
15
#include "prio.h"
16
#if defined(XP_WIN)
17
#include <windows.h>
18
#elif defined(MOZ_WIDGET_COCOA)
19
#include <CoreServices/CoreServices.h>
20
#include "nsCocoaFeatures.h"
21
#elif defined(MOZ_WIDGET_GTK)
22
#include <gtk/gtk.h>
23
#endif
24
25
#ifdef MOZ_WIDGET_ANDROID
26
#include "AndroidBridge.h"
27
#endif
28
29
#include "mozilla/Services.h"
30
31
#include "nsCRT.h"
32
#include "nsConsoleMessage.h"
33
#include "nsTextFormatter.h"
34
#include "nsVersionComparator.h"
35
#include "nsXPCOMCIDInternal.h"
36
37
#include "nsIConsoleService.h"
38
#include "nsIScriptError.h"
39
#include "nsIXULAppInfo.h"
40
#include "nsIXULRuntime.h"
41
42
using namespace mozilla;
43
44
struct ManifestDirective
45
{
46
  const char* directive;
47
  int argc;
48
49
  bool ischrome;
50
51
  // The contentaccessible flags only apply to content/resource directives.
52
  bool contentflags;
53
54
  // Function to handle this directive. This isn't a union because C++ still
55
  // hasn't learned how to initialize unions in a sane way.
56
  void (nsComponentManagerImpl::*mgrfunc)(
57
    nsComponentManagerImpl::ManifestProcessingContext& aCx,
58
    int aLineNo, char* const* aArgv);
59
  void (nsChromeRegistry::*regfunc)(
60
    nsChromeRegistry::ManifestProcessingContext& aCx,
61
    int aLineNo, char* const* aArgv, int aFlags);
62
};
63
static const ManifestDirective kParsingTable[] = {
64
  {
65
    "manifest",         1, true, false,
66
    &nsComponentManagerImpl::ManifestManifest, nullptr,
67
  },
68
  {
69
    "component",        2, false, false,
70
    &nsComponentManagerImpl::ManifestComponent, nullptr,
71
  },
72
  {
73
    "contract",         2, false, false,
74
    &nsComponentManagerImpl::ManifestContract, nullptr,
75
  },
76
  {
77
    "category",         3, false, false,
78
    &nsComponentManagerImpl::ManifestCategory, nullptr,
79
  },
80
  {
81
    "content",          2, true,  true,
82
    nullptr, &nsChromeRegistry::ManifestContent,
83
  },
84
  {
85
    "locale",           3, true, false,
86
    nullptr, &nsChromeRegistry::ManifestLocale,
87
  },
88
  {
89
    "skin",             3, true, false,
90
    nullptr, &nsChromeRegistry::ManifestSkin,
91
  },
92
  {
93
    // NB: note that while skin manifests can use this, they are only allowed
94
    // to use it for chrome://../skin/ URLs
95
    "override",         2, true, false,
96
    nullptr, &nsChromeRegistry::ManifestOverride,
97
  },
98
  {
99
    "resource",         2, false, true,
100
    nullptr, &nsChromeRegistry::ManifestResource,
101
  }
102
};
103
104
static const char kWhitespace[] = "\t ";
105
106
static bool
107
IsNewline(char aChar)
108
73.9k
{
109
73.9k
  return aChar == '\n' || aChar == '\r';
110
73.9k
}
111
112
void
113
LogMessage(const char* aMsg, ...)
114
0
{
115
0
  MOZ_ASSERT(nsComponentManagerImpl::gComponentManager);
116
0
117
0
  nsCOMPtr<nsIConsoleService> console =
118
0
    do_GetService(NS_CONSOLESERVICE_CONTRACTID);
119
0
  if (!console) {
120
0
    return;
121
0
  }
122
0
123
0
  va_list args;
124
0
  va_start(args, aMsg);
125
0
  SmprintfPointer formatted(mozilla::Vsmprintf(aMsg, args));
126
0
  va_end(args);
127
0
128
0
  nsCOMPtr<nsIConsoleMessage> error =
129
0
    new nsConsoleMessage(NS_ConvertUTF8toUTF16(formatted.get()).get());
130
0
  console->LogMessage(error);
131
0
}
132
133
void
134
LogMessageWithContext(FileLocation& aFile,
135
                      uint32_t aLineNumber, const char* aMsg, ...)
136
0
{
137
0
  va_list args;
138
0
  va_start(args, aMsg);
139
0
  SmprintfPointer formatted(mozilla::Vsmprintf(aMsg, args));
140
0
  va_end(args);
141
0
  if (!formatted) {
142
0
    return;
143
0
  }
144
0
145
0
  MOZ_ASSERT(nsComponentManagerImpl::gComponentManager);
146
0
147
0
  nsCString file;
148
0
  aFile.GetURIString(file);
149
0
150
0
  nsCOMPtr<nsIScriptError> error =
151
0
    do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
152
0
  if (!error) {
153
0
    // This can happen early in component registration. Fall back to a
154
0
    // generic console message.
155
0
    LogMessage("Warning: in '%s', line %i: %s", file.get(),
156
0
               aLineNumber, formatted.get());
157
0
    return;
158
0
  }
159
0
160
0
  nsCOMPtr<nsIConsoleService> console =
161
0
    do_GetService(NS_CONSOLESERVICE_CONTRACTID);
162
0
  if (!console) {
163
0
    return;
164
0
  }
165
0
166
0
  nsresult rv = error->Init(NS_ConvertUTF8toUTF16(formatted.get()),
167
0
                            NS_ConvertUTF8toUTF16(file), EmptyString(),
168
0
                            aLineNumber, 0, nsIScriptError::warningFlag,
169
0
                            "chrome registration",
170
0
                            false /* from private window */);
171
0
  if (NS_FAILED(rv)) {
172
0
    return;
173
0
  }
174
0
175
0
  console->LogMessage(error);
176
0
}
177
178
/**
179
 * Check for a modifier flag of the following forms:
180
 *   "flag"   (same as "true")
181
 *   "flag=yes|true|1"
182
 *   "flag="no|false|0"
183
 * @param aFlag The flag to compare.
184
 * @param aData The tokenized data to check; this is lowercased
185
 *              before being passed in.
186
 * @param aResult If the flag is found, the value is assigned here.
187
 * @return Whether the flag was handled.
188
 */
189
static bool
190
CheckFlag(const nsAString& aFlag, const nsAString& aData, bool& aResult)
191
18
{
192
18
  if (!StringBeginsWith(aData, aFlag)) {
193
0
    return false;
194
0
  }
195
18
196
18
  if (aFlag.Length() == aData.Length()) {
197
0
    // the data is simply "flag", which is the same as "flag=yes"
198
0
    aResult = true;
199
0
    return true;
200
0
  }
201
18
202
18
  if (aData.CharAt(aFlag.Length()) != '=') {
203
0
    // the data is "flag2=", which is not anything we care about
204
0
    return false;
205
0
  }
206
18
207
18
  if (aData.Length() == aFlag.Length() + 1) {
208
0
    aResult = false;
209
0
    return true;
210
0
  }
211
18
212
18
  switch (aData.CharAt(aFlag.Length() + 1)) {
213
18
    case '1':
214
18
    case 't': //true
215
18
    case 'y': //yes
216
18
      aResult = true;
217
18
      return true;
218
18
219
18
    case '0':
220
0
    case 'f': //false
221
0
    case 'n': //no
222
0
      aResult = false;
223
0
      return true;
224
0
  }
225
0
226
0
  return false;
227
0
}
228
229
enum TriState
230
{
231
  eUnspecified,
232
  eBad,
233
  eOK
234
};
235
236
/**
237
 * Check for a modifier flag of the following form:
238
 *   "flag=string"
239
 *   "flag!=string"
240
 * @param aFlag The flag to compare.
241
 * @param aData The tokenized data to check; this is lowercased
242
 *              before being passed in.
243
 * @param aValue The value that is expected.
244
 * @param aResult If this is "ok" when passed in, this is left alone.
245
 *                Otherwise if the flag is found it is set to eBad or eOK.
246
 * @return Whether the flag was handled.
247
 */
248
static bool
249
CheckStringFlag(const nsAString& aFlag, const nsAString& aData,
250
                const nsAString& aValue, TriState& aResult)
251
369
{
252
369
  if (aData.Length() < aFlag.Length() + 1) {
253
12
    return false;
254
12
  }
255
357
256
357
  if (!StringBeginsWith(aData, aFlag)) {
257
270
    return false;
258
270
  }
259
87
260
87
  bool comparison = true;
261
87
  if (aData[aFlag.Length()] != '=') {
262
0
    if (aData[aFlag.Length()] == '!' &&
263
0
        aData.Length() >= aFlag.Length() + 2 &&
264
0
        aData[aFlag.Length() + 1] == '=') {
265
0
      comparison = false;
266
0
    } else {
267
0
      return false;
268
0
    }
269
87
  }
270
87
271
87
  if (aResult != eOK) {
272
84
    nsDependentSubstring testdata =
273
84
      Substring(aData, aFlag.Length() + (comparison ? 1 : 2));
274
84
    if (testdata.Equals(aValue)) {
275
60
      aResult = comparison ? eOK : eBad;
276
60
    } else {
277
24
      aResult = comparison ? eBad : eOK;
278
24
    }
279
84
  }
280
87
281
87
  return true;
282
87
}
283
284
static bool
285
CheckOsFlag(const nsAString& aFlag, const nsAString& aData,
286
            const nsAString& aValue, TriState& aResult)
287
96
{
288
96
  bool result = CheckStringFlag(aFlag, aData, aValue, aResult);
289
96
#if defined(XP_UNIX) && !defined(XP_DARWIN) && !defined(ANDROID)
290
96
  if (result && aResult == eBad) {
291
9
    result = CheckStringFlag(aFlag, aData, NS_LITERAL_STRING("likeunix"), aResult);
292
9
  }
293
96
#endif
294
96
  return result;
295
96
}
296
297
/**
298
 * Check for a modifier flag of the following form:
299
 *   "flag=version"
300
 *   "flag<=version"
301
 *   "flag<version"
302
 *   "flag>=version"
303
 *   "flag>version"
304
 * @param aFlag The flag to compare.
305
 * @param aData The tokenized data to check; this is lowercased
306
 *              before being passed in.
307
 * @param aValue The value that is expected. If this is empty then no
308
 *               comparison will match.
309
 * @param aResult If this is eOK when passed in, this is left alone.
310
 *                Otherwise if the flag is found it is set to eBad or eOK.
311
 * @return Whether the flag was handled.
312
 */
313
314
0
#define COMPARE_EQ    1 << 0
315
0
#define COMPARE_LT    1 << 1
316
0
#define COMPARE_GT    1 << 2
317
318
static bool
319
CheckVersionFlag(const nsString& aFlag, const nsString& aData,
320
                 const nsString& aValue, TriState& aResult)
321
54
{
322
54
  if (aData.Length() < aFlag.Length() + 2) {
323
0
    return false;
324
0
  }
325
54
326
54
  if (!StringBeginsWith(aData, aFlag)) {
327
54
    return false;
328
54
  }
329
0
330
0
  if (aValue.Length() == 0) {
331
0
    if (aResult != eOK) {
332
0
      aResult = eBad;
333
0
    }
334
0
    return true;
335
0
  }
336
0
337
0
  uint32_t comparison;
338
0
  nsAutoString testdata;
339
0
340
0
  switch (aData[aFlag.Length()]) {
341
0
    case '=':
342
0
      comparison = COMPARE_EQ;
343
0
      testdata = Substring(aData, aFlag.Length() + 1);
344
0
      break;
345
0
346
0
    case '<':
347
0
      if (aData[aFlag.Length() + 1] == '=') {
348
0
        comparison = COMPARE_EQ | COMPARE_LT;
349
0
        testdata = Substring(aData, aFlag.Length() + 2);
350
0
      } else {
351
0
        comparison = COMPARE_LT;
352
0
        testdata = Substring(aData, aFlag.Length() + 1);
353
0
      }
354
0
      break;
355
0
356
0
    case '>':
357
0
      if (aData[aFlag.Length() + 1] == '=') {
358
0
        comparison = COMPARE_EQ | COMPARE_GT;
359
0
        testdata = Substring(aData, aFlag.Length() + 2);
360
0
      } else {
361
0
        comparison = COMPARE_GT;
362
0
        testdata = Substring(aData, aFlag.Length() + 1);
363
0
      }
364
0
      break;
365
0
366
0
    default:
367
0
      return false;
368
0
  }
369
0
370
0
  if (testdata.Length() == 0) {
371
0
    return false;
372
0
  }
373
0
374
0
  if (aResult != eOK) {
375
0
    int32_t c = mozilla::CompareVersions(NS_ConvertUTF16toUTF8(aValue).get(),
376
0
                                         NS_ConvertUTF16toUTF8(testdata).get());
377
0
    if ((c == 0 && comparison & COMPARE_EQ) ||
378
0
        (c < 0 && comparison & COMPARE_LT) ||
379
0
        (c > 0 && comparison & COMPARE_GT)) {
380
0
      aResult = eOK;
381
0
    } else {
382
0
      aResult = eBad;
383
0
    }
384
0
  }
385
0
386
0
  return true;
387
0
}
388
389
// In-place conversion of ascii characters to lower case
390
static void
391
ToLowerCase(char* aToken)
392
96
{
393
1.40k
  for (; *aToken; ++aToken) {
394
1.31k
    *aToken = NS_ToLower(*aToken);
395
1.31k
  }
396
96
}
397
398
namespace {
399
400
struct CachedDirective
401
{
402
  int lineno;
403
  char* argv[4];
404
};
405
406
} // namespace
407
408
409
void
410
ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf,
411
              bool aChromeOnly)
412
12
{
413
12
  nsComponentManagerImpl::ManifestProcessingContext mgrcx(aType, aFile,
414
12
                                                          aChromeOnly);
415
12
  nsChromeRegistry::ManifestProcessingContext chromecx(aType, aFile);
416
12
  nsresult rv;
417
12
418
12
  NS_NAMED_LITERAL_STRING(kContentAccessible, "contentaccessible");
419
12
  NS_NAMED_LITERAL_STRING(kRemoteEnabled, "remoteenabled");
420
12
  NS_NAMED_LITERAL_STRING(kRemoteRequired, "remoterequired");
421
12
  NS_NAMED_LITERAL_STRING(kApplication, "application");
422
12
  NS_NAMED_LITERAL_STRING(kAppVersion, "appversion");
423
12
  NS_NAMED_LITERAL_STRING(kGeckoVersion, "platformversion");
424
12
  NS_NAMED_LITERAL_STRING(kOs, "os");
425
12
  NS_NAMED_LITERAL_STRING(kOsVersion, "osversion");
426
12
  NS_NAMED_LITERAL_STRING(kABI, "abi");
427
12
  NS_NAMED_LITERAL_STRING(kProcess, "process");
428
#if defined(MOZ_WIDGET_ANDROID)
429
  NS_NAMED_LITERAL_STRING(kTablet, "tablet");
430
#endif
431
432
12
  NS_NAMED_LITERAL_STRING(kMain, "main");
433
12
  NS_NAMED_LITERAL_STRING(kContent, "content");
434
12
435
12
  // Obsolete
436
12
  NS_NAMED_LITERAL_STRING(kXPCNativeWrappers, "xpcnativewrappers");
437
12
438
12
  nsAutoString appID;
439
12
  nsAutoString appVersion;
440
12
  nsAutoString geckoVersion;
441
12
  nsAutoString osTarget;
442
12
  nsAutoString abi;
443
12
  nsAutoString process;
444
12
445
12
  nsCOMPtr<nsIXULAppInfo> xapp(do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
446
12
  if (xapp) {
447
12
    nsAutoCString s;
448
12
    rv = xapp->GetID(s);
449
12
    if (NS_SUCCEEDED(rv)) {
450
12
      CopyUTF8toUTF16(s, appID);
451
12
    }
452
12
453
12
    rv = xapp->GetVersion(s);
454
12
    if (NS_SUCCEEDED(rv)) {
455
12
      CopyUTF8toUTF16(s, appVersion);
456
12
    }
457
12
458
12
    rv = xapp->GetPlatformVersion(s);
459
12
    if (NS_SUCCEEDED(rv)) {
460
12
      CopyUTF8toUTF16(s, geckoVersion);
461
12
    }
462
12
463
12
    nsCOMPtr<nsIXULRuntime> xruntime(do_QueryInterface(xapp));
464
12
    if (xruntime) {
465
12
      rv = xruntime->GetOS(s);
466
12
      if (NS_SUCCEEDED(rv)) {
467
12
        ToLowerCase(s);
468
12
        CopyUTF8toUTF16(s, osTarget);
469
12
      }
470
12
471
12
      rv = xruntime->GetXPCOMABI(s);
472
12
      if (NS_SUCCEEDED(rv) && osTarget.Length()) {
473
12
        ToLowerCase(s);
474
12
        CopyUTF8toUTF16(s, abi);
475
12
        abi.Insert(char16_t('_'), 0);
476
12
        abi.Insert(osTarget, 0);
477
12
      }
478
12
    }
479
12
  }
480
12
481
12
  nsAutoString osVersion;
482
#if defined(XP_WIN)
483
#pragma warning(push)
484
#pragma warning(disable:4996) // VC12+ deprecates GetVersionEx
485
  OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
486
  if (GetVersionEx(&info)) {
487
    nsTextFormatter::ssprintf(osVersion, u"%ld.%ld",
488
                              info.dwMajorVersion,
489
                              info.dwMinorVersion);
490
  }
491
#pragma warning(pop)
492
#elif defined(MOZ_WIDGET_COCOA)
493
  SInt32 majorVersion = nsCocoaFeatures::OSXVersionMajor();
494
  SInt32 minorVersion = nsCocoaFeatures::OSXVersionMinor();
495
  nsTextFormatter::ssprintf(osVersion, u"%ld.%ld",
496
                            majorVersion,
497
                            minorVersion);
498
#elif defined(MOZ_WIDGET_GTK)
499
  nsTextFormatter::ssprintf(osVersion, u"%ld.%ld",
500
12
                            gtk_major_version,
501
12
                            gtk_minor_version);
502
#elif defined(MOZ_WIDGET_ANDROID)
503
  bool isTablet = false;
504
  if (mozilla::AndroidBridge::Bridge()) {
505
    mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION",
506
                                                           "RELEASE",
507
                                                           osVersion);
508
    isTablet = java::GeckoAppShell::IsTablet();
509
  }
510
#endif
511
512
12
  if (XRE_IsContentProcess()) {
513
0
    process = kContent;
514
12
  } else {
515
12
    process = kMain;
516
12
  }
517
12
518
12
  // Because contracts must be registered after CIDs, we save and process them
519
12
  // at the end.
520
12
  nsTArray<CachedDirective> contracts;
521
12
522
12
  char* token;
523
12
  char* newline = aBuf;
524
12
  uint32_t line = 0;
525
12
526
12
  // outer loop tokenizes by newline
527
927
  while (*newline) {
528
915
    while (*newline && IsNewline(*newline)) {
529
0
      ++newline;
530
0
      ++line;
531
0
    }
532
915
    if (!*newline) {
533
0
      break;
534
0
    }
535
915
536
915
    token = newline;
537
73.0k
    while (*newline && !IsNewline(*newline)) {
538
72.1k
      ++newline;
539
72.1k
    }
540
915
541
915
    if (*newline) {
542
915
      *newline = '\0';
543
915
      ++newline;
544
915
    }
545
915
    ++line;
546
915
547
915
    if (*token == '#') { // ignore lines that begin with # as comments
548
0
      continue;
549
0
    }
550
915
551
915
    char* whitespace = token;
552
915
    token = nsCRT::strtok(whitespace, kWhitespace, &whitespace);
553
915
    if (!token) {
554
0
      continue;
555
0
    }
556
915
557
915
    const ManifestDirective* directive = nullptr;
558
915
    for (const ManifestDirective* d = kParsingTable;
559
3.03k
         d < ArrayEnd(kParsingTable);
560
3.03k
         ++d) {
561
3.03k
      if (!strcmp(d->directive, token)) {
562
915
        directive = d;
563
915
        break;
564
915
      }
565
3.03k
    }
566
915
567
915
    if (!directive) {
568
0
      LogMessageWithContext(aFile, line,
569
0
                            "Ignoring unrecognized chrome manifest directive '%s'.",
570
0
                            token);
571
0
      continue;
572
0
    }
573
915
574
915
    if (!directive->ischrome && NS_BOOTSTRAPPED_LOCATION == aType) {
575
0
      LogMessageWithContext(aFile, line,
576
0
                            "Bootstrapped manifest not allowed to use '%s' directive.",
577
0
                            token);
578
0
      continue;
579
0
    }
580
915
581
915
    NS_ASSERTION(directive->argc < 4, "Need to reset argv array length");
582
915
    char* argv[4];
583
2.90k
    for (int i = 0; i < directive->argc; ++i) {
584
1.98k
      argv[i] = nsCRT::strtok(whitespace, kWhitespace, &whitespace);
585
1.98k
    }
586
915
587
915
    if (!argv[directive->argc - 1]) {
588
0
      LogMessageWithContext(aFile, line,
589
0
                            "Not enough arguments for chrome manifest directive '%s', expected %i.",
590
0
                            token, directive->argc);
591
0
      continue;
592
0
    }
593
915
594
915
    bool ok = true;
595
915
    TriState stAppVersion = eUnspecified;
596
915
    TriState stGeckoVersion = eUnspecified;
597
915
    TriState stApp = eUnspecified;
598
915
    TriState stOsVersion = eUnspecified;
599
915
    TriState stOs = eUnspecified;
600
915
    TriState stABI = eUnspecified;
601
915
    TriState stProcess = eUnspecified;
602
#if defined(MOZ_WIDGET_ANDROID)
603
    TriState stTablet = eUnspecified;
604
#endif
605
    int flags = 0;
606
915
607
1.01k
    while ((token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) &&
608
1.01k
           ok) {
609
96
      ToLowerCase(token);
610
96
      NS_ConvertASCIItoUTF16 wtoken(token);
611
96
612
96
      if (CheckStringFlag(kApplication, wtoken, appID, stApp) ||
613
96
          CheckOsFlag(kOs, wtoken, osTarget, stOs) ||
614
96
          CheckStringFlag(kABI, wtoken, abi, stABI) ||
615
96
          CheckStringFlag(kProcess, wtoken, process, stProcess) ||
616
96
          CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) ||
617
96
          CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) ||
618
96
          CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, stGeckoVersion)) {
619
78
        continue;
620
78
      }
621
18
622
#if defined(MOZ_WIDGET_ANDROID)
623
      bool tablet = false;
624
      if (CheckFlag(kTablet, wtoken, tablet)) {
625
        stTablet = (tablet == isTablet) ? eOK : eBad;
626
        continue;
627
      }
628
#endif
629
630
18
      if (directive->contentflags) {
631
18
        bool flag;
632
18
        if (CheckFlag(kContentAccessible, wtoken, flag)) {
633
18
          if (flag)
634
18
            flags |= nsChromeRegistry::CONTENT_ACCESSIBLE;
635
18
          continue;
636
18
        }
637
0
        if (CheckFlag(kRemoteEnabled, wtoken, flag)) {
638
0
          if (flag)
639
0
            flags |= nsChromeRegistry::REMOTE_ALLOWED;
640
0
          continue;
641
0
        }
642
0
        if (CheckFlag(kRemoteRequired, wtoken, flag)) {
643
0
          if (flag)
644
0
            flags |= nsChromeRegistry::REMOTE_REQUIRED;
645
0
          continue;
646
0
        }
647
0
      }
648
0
649
0
      bool xpcNativeWrappers = true; // Dummy for CheckFlag.
650
0
      if (CheckFlag(kXPCNativeWrappers, wtoken, xpcNativeWrappers)) {
651
0
        LogMessageWithContext(aFile, line,
652
0
                              "Ignoring obsolete chrome registration modifier '%s'.",
653
0
                              token);
654
0
        continue;
655
0
      }
656
0
657
0
      LogMessageWithContext(aFile, line,
658
0
                            "Unrecognized chrome manifest modifier '%s'.",
659
0
                            token);
660
0
      ok = false;
661
0
    }
662
915
663
915
    if (!ok ||
664
915
        stApp == eBad ||
665
915
        stAppVersion == eBad ||
666
915
        stGeckoVersion == eBad ||
667
915
        stOs == eBad ||
668
915
        stOsVersion == eBad ||
669
#ifdef MOZ_WIDGET_ANDROID
670
        stTablet == eBad ||
671
#endif
672
909
        stABI == eBad ||
673
915
        stProcess == eBad) {
674
15
      continue;
675
15
    }
676
900
677
900
    if (directive->regfunc) {
678
129
      if (GeckoProcessType_Default != XRE_GetProcessType()) {
679
0
        continue;
680
0
      }
681
129
682
129
      if (!nsChromeRegistry::gChromeRegistry) {
683
3
        nsCOMPtr<nsIChromeRegistry> cr =
684
3
          mozilla::services::GetChromeRegistryService();
685
3
        if (!nsChromeRegistry::gChromeRegistry) {
686
0
          LogMessageWithContext(aFile, line,
687
0
                                "Chrome registry isn't available yet.");
688
0
          continue;
689
0
        }
690
129
      }
691
129
692
129
      (nsChromeRegistry::gChromeRegistry->*(directive->regfunc))(
693
129
        chromecx, line, argv, flags);
694
771
    } else if (directive->ischrome || !aChromeOnly) {
695
771
      (nsComponentManagerImpl::gComponentManager->*(directive->mgrfunc))(
696
771
        mgrcx, line, argv);
697
771
    }
698
900
  }
699
12
700
12
  for (uint32_t i = 0; i < contracts.Length(); ++i) {
701
0
    CachedDirective& d = contracts[i];
702
0
    nsComponentManagerImpl::gComponentManager->ManifestContract(mgrcx,
703
0
                                                                d.lineno,
704
0
                                                                d.argv);
705
0
  }
706
12
}