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