1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Firefox
16 : *
17 : * The Initial Developer of the Original Code is
18 : * the Mozilla Foundation <http://www.mozilla.org/>.
19 : * Portions created by the Initial Developer are Copyright (C) 2010
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Philipp Kewisch <mozilla@kewis.ch>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "mozilla/Util.h"
40 :
41 : #include "ManifestParser.h"
42 :
43 : #include <string.h>
44 :
45 : #include "prio.h"
46 : #include "prprf.h"
47 : #if defined(XP_WIN)
48 : #include <windows.h>
49 : #elif defined(MOZ_WIDGET_COCOA)
50 : #include <CoreServices/CoreServices.h>
51 : #elif defined(MOZ_WIDGET_GTK2)
52 : #include <gtk/gtk.h>
53 : #endif
54 :
55 : #ifdef MOZ_WIDGET_ANDROID
56 : #include "AndroidBridge.h"
57 : #endif
58 :
59 : #include "mozilla/Services.h"
60 :
61 : #include "nsCRT.h"
62 : #include "nsConsoleMessage.h"
63 : #include "nsTextFormatter.h"
64 : #include "nsVersionComparator.h"
65 : #include "nsXPCOMCIDInternal.h"
66 :
67 : #include "nsIConsoleService.h"
68 : #include "nsIScriptError.h"
69 : #include "nsIXULAppInfo.h"
70 : #include "nsIXULRuntime.h"
71 :
72 : using namespace mozilla;
73 :
74 : struct ManifestDirective
75 : {
76 : const char* directive;
77 : int argc;
78 :
79 : // Some directives should only be delivered for NS_COMPONENT_LOCATION
80 : // manifests.
81 : bool componentonly;
82 :
83 : bool ischrome;
84 :
85 : bool allowbootstrap;
86 :
87 : // The platform/contentaccessible flags only apply to content directives.
88 : bool contentflags;
89 :
90 : // Function to handle this directive. This isn't a union because C++ still
91 : // hasn't learned how to initialize unions in a sane way.
92 : void (nsComponentManagerImpl::*mgrfunc)
93 : (nsComponentManagerImpl::ManifestProcessingContext& cx,
94 : int lineno, char *const * argv);
95 : void (nsChromeRegistry::*regfunc)
96 : (nsChromeRegistry::ManifestProcessingContext& cx,
97 : int lineno, char *const *argv,
98 : bool platform, bool contentaccessible);
99 :
100 : bool isContract;
101 : };
102 : static const ManifestDirective kParsingTable[] = {
103 : { "manifest", 1, false, true, true, false,
104 : &nsComponentManagerImpl::ManifestManifest, NULL },
105 : { "binary-component", 1, true, false, false, false,
106 : &nsComponentManagerImpl::ManifestBinaryComponent, NULL },
107 : { "interfaces", 1, true, false, false, false,
108 : &nsComponentManagerImpl::ManifestXPT, NULL },
109 : { "component", 2, true, false, false, false,
110 : &nsComponentManagerImpl::ManifestComponent, NULL },
111 : { "contract", 2, true, false, false, false,
112 : &nsComponentManagerImpl::ManifestContract, NULL, true},
113 : { "category", 3, true, false, false, false,
114 : &nsComponentManagerImpl::ManifestCategory, NULL },
115 : { "content", 2, true, true, true, true,
116 : NULL, &nsChromeRegistry::ManifestContent },
117 : { "locale", 3, true, true, true, false,
118 : NULL, &nsChromeRegistry::ManifestLocale },
119 : { "skin", 3, false, true, true, false,
120 : NULL, &nsChromeRegistry::ManifestSkin },
121 : { "overlay", 2, true, true, false, false,
122 : NULL, &nsChromeRegistry::ManifestOverlay },
123 : { "style", 2, false, true, false, false,
124 : NULL, &nsChromeRegistry::ManifestStyle },
125 : { "override", 2, true, true, true, false,
126 : NULL, &nsChromeRegistry::ManifestOverride },
127 : { "resource", 2, true, true, false, false,
128 : NULL, &nsChromeRegistry::ManifestResource }
129 : };
130 :
131 : static const char kWhitespace[] = "\t ";
132 :
133 51538915 : static bool IsNewline(char c)
134 : {
135 51538915 : return c == '\n' || c == '\r';
136 : }
137 :
138 : namespace {
139 : struct AutoPR_smprintf_free
140 : {
141 1387 : AutoPR_smprintf_free(char* buf)
142 1387 : : mBuf(buf)
143 : {
144 1387 : }
145 :
146 1387 : ~AutoPR_smprintf_free()
147 : {
148 1387 : if (mBuf)
149 1387 : PR_smprintf_free(mBuf);
150 1387 : }
151 :
152 2773 : operator char*() const {
153 2773 : return mBuf;
154 : }
155 :
156 : char* mBuf;
157 : };
158 :
159 : } // anonymous namespace
160 :
161 1 : void LogMessage(const char* aMsg, ...)
162 : {
163 : nsCOMPtr<nsIConsoleService> console =
164 2 : do_GetService(NS_CONSOLESERVICE_CONTRACTID);
165 1 : if (!console)
166 : return;
167 :
168 : va_list args;
169 1 : va_start(args, aMsg);
170 2 : AutoPR_smprintf_free formatted(PR_vsmprintf(aMsg, args));
171 1 : va_end(args);
172 :
173 : nsCOMPtr<nsIConsoleMessage> error =
174 3 : new nsConsoleMessage(NS_ConvertUTF8toUTF16(formatted).get());
175 1 : console->LogMessage(error);
176 : }
177 :
178 1386 : void LogMessageWithContext(FileLocation &aFile,
179 : PRUint32 aLineNumber, const char* aMsg, ...)
180 : {
181 : va_list args;
182 1386 : va_start(args, aMsg);
183 2772 : AutoPR_smprintf_free formatted(PR_vsmprintf(aMsg, args));
184 1386 : va_end(args);
185 1386 : if (!formatted)
186 : return;
187 :
188 2772 : nsCString file;
189 1386 : aFile.GetURIString(file);
190 :
191 : nsCOMPtr<nsIScriptError> error =
192 2772 : do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
193 1386 : if (!error) {
194 : // This can happen early in component registration. Fall back to a
195 : // generic console message.
196 : LogMessage("Warning: in '%s', line %i: %s", file.get(),
197 0 : aLineNumber, (char*) formatted);
198 : return;
199 : }
200 :
201 : nsCOMPtr<nsIConsoleService> console =
202 2772 : do_GetService(NS_CONSOLESERVICE_CONTRACTID);
203 1386 : if (!console)
204 : return;
205 :
206 4158 : nsresult rv = error->Init(NS_ConvertUTF8toUTF16(formatted).get(),
207 1386 : NS_ConvertUTF8toUTF16(file).get(), NULL,
208 : aLineNumber, 0, nsIScriptError::warningFlag,
209 2772 : "chrome registration");
210 1386 : if (NS_FAILED(rv))
211 : return;
212 :
213 2772 : console->LogMessage(error);
214 : }
215 :
216 : /**
217 : * Check for a modifier flag of the following forms:
218 : * "flag" (same as "true")
219 : * "flag=yes|true|1"
220 : * "flag="no|false|0"
221 : * @param aFlag The flag to compare.
222 : * @param aData The tokenized data to check; this is lowercased
223 : * before being passed in.
224 : * @param aResult If the flag is found, the value is assigned here.
225 : * @return Whether the flag was handled.
226 : */
227 : static bool
228 11032 : CheckFlag(const nsSubstring& aFlag, const nsSubstring& aData, bool& aResult)
229 : {
230 11032 : if (!StringBeginsWith(aData, aFlag))
231 4746 : return false;
232 :
233 6286 : if (aFlag.Length() == aData.Length()) {
234 : // the data is simply "flag", which is the same as "flag=yes"
235 1572 : aResult = true;
236 1572 : return true;
237 : }
238 :
239 4714 : if (aData.CharAt(aFlag.Length()) != '=') {
240 : // the data is "flag2=", which is not anything we care about
241 0 : return false;
242 : }
243 :
244 4714 : if (aData.Length() == aFlag.Length() + 1) {
245 0 : aResult = false;
246 0 : return true;
247 : }
248 :
249 4714 : switch (aData.CharAt(aFlag.Length() + 1)) {
250 : case '1':
251 : case 't': //true
252 : case 'y': //yes
253 4712 : aResult = true;
254 4712 : return true;
255 :
256 : case '0':
257 : case 'f': //false
258 : case 'n': //no
259 2 : aResult = false;
260 2 : return true;
261 : }
262 :
263 0 : return false;
264 : }
265 :
266 : enum TriState {
267 : eUnspecified,
268 : eBad,
269 : eOK
270 : };
271 :
272 : /**
273 : * Check for a modifier flag of the following form:
274 : * "flag=string"
275 : * "flag!=string"
276 : * @param aFlag The flag to compare.
277 : * @param aData The tokenized data to check; this is lowercased
278 : * before being passed in.
279 : * @param aValue The value that is expected.
280 : * @param aResult If this is "ok" when passed in, this is left alone.
281 : * Otherwise if the flag is found it is set to eBad or eOK.
282 : * @return Whether the flag was handled.
283 : */
284 : static bool
285 77063 : CheckStringFlag(const nsSubstring& aFlag, const nsSubstring& aData,
286 : const nsSubstring& aValue, TriState& aResult)
287 : {
288 77063 : if (aData.Length() < aFlag.Length() + 1)
289 11004 : return false;
290 :
291 66059 : if (!StringBeginsWith(aData, aFlag))
292 20504 : return false;
293 :
294 45555 : bool comparison = true;
295 45555 : if (aData[aFlag.Length()] != '=') {
296 12590 : if (aData[aFlag.Length()] == '!' &&
297 3150 : aData.Length() >= aFlag.Length() + 2 &&
298 3150 : aData[aFlag.Length() + 1] == '=')
299 3148 : comparison = false;
300 : else
301 3142 : return false;
302 : }
303 :
304 42413 : if (aResult != eOK) {
305 84826 : nsDependentSubstring testdata = Substring(aData, aFlag.Length() + (comparison ? 1 : 2));
306 42413 : if (testdata.Equals(aValue))
307 9 : aResult = comparison ? eOK : eBad;
308 : else
309 42404 : aResult = comparison ? eBad : eOK;
310 : }
311 :
312 42413 : return true;
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 22060 : CheckVersionFlag(const nsString& aFlag, const nsString& aData,
338 : const nsString& aValue, TriState& aResult)
339 : {
340 22060 : if (aData.Length() < aFlag.Length() + 2)
341 4728 : return false;
342 :
343 17332 : if (!StringBeginsWith(aData, aFlag))
344 14176 : return false;
345 :
346 3156 : if (aValue.Length() == 0) {
347 8 : if (aResult != eOK)
348 8 : aResult = eBad;
349 8 : return true;
350 : }
351 :
352 : PRUint32 comparison;
353 6296 : nsAutoString testdata;
354 :
355 3148 : switch (aData[aFlag.Length()]) {
356 : case '=':
357 2 : comparison = COMPARE_EQ;
358 2 : testdata = Substring(aData, aFlag.Length() + 1);
359 2 : break;
360 :
361 : case '<':
362 3143 : if (aData[aFlag.Length() + 1] == '=') {
363 1 : comparison = COMPARE_EQ | COMPARE_LT;
364 1 : testdata = Substring(aData, aFlag.Length() + 2);
365 : }
366 : else {
367 3142 : comparison = COMPARE_LT;
368 3142 : testdata = Substring(aData, aFlag.Length() + 1);
369 : }
370 3143 : break;
371 :
372 : case '>':
373 3 : if (aData[aFlag.Length() + 1] == '=') {
374 1 : comparison = COMPARE_EQ | COMPARE_GT;
375 1 : testdata = Substring(aData, aFlag.Length() + 2);
376 : }
377 : else {
378 2 : comparison = COMPARE_GT;
379 2 : testdata = Substring(aData, aFlag.Length() + 1);
380 : }
381 3 : break;
382 :
383 : default:
384 0 : return false;
385 : }
386 :
387 3148 : if (testdata.Length() == 0)
388 0 : return false;
389 :
390 3148 : if (aResult != eOK) {
391 3148 : PRInt32 c = NS_CompareVersions(NS_ConvertUTF16toUTF8(aValue).get(),
392 6296 : NS_ConvertUTF16toUTF8(testdata).get());
393 3148 : if ((c == 0 && comparison & COMPARE_EQ) ||
394 : (c < 0 && comparison & COMPARE_LT) ||
395 : (c > 0 && comparison & COMPARE_GT))
396 3145 : aResult = eOK;
397 : else
398 3 : aResult = eBad;
399 : }
400 :
401 3148 : return true;
402 : }
403 :
404 : // In-place conversion of ascii characters to lower case
405 : static void
406 51865 : ToLowerCase(char* token)
407 : {
408 2058025 : for (; *token; ++token)
409 2006160 : *token = NS_ToLower(*token);
410 51865 : }
411 :
412 : namespace {
413 :
414 : struct CachedDirective
415 132427 : {
416 : int lineno;
417 : char* argv[4];
418 : };
419 :
420 : } // anonymous namespace
421 :
422 :
423 : void
424 95818 : ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOnly)
425 : {
426 191636 : nsComponentManagerImpl::ManifestProcessingContext mgrcx(type, file, aChromeOnly);
427 191636 : nsChromeRegistry::ManifestProcessingContext chromecx(type, file);
428 : nsresult rv;
429 :
430 191636 : NS_NAMED_LITERAL_STRING(kPlatform, "platform");
431 191636 : NS_NAMED_LITERAL_STRING(kContentAccessible, "contentaccessible");
432 191636 : NS_NAMED_LITERAL_STRING(kApplication, "application");
433 191636 : NS_NAMED_LITERAL_STRING(kAppVersion, "appversion");
434 191636 : NS_NAMED_LITERAL_STRING(kGeckoVersion, "platformversion");
435 191636 : NS_NAMED_LITERAL_STRING(kOs, "os");
436 191636 : NS_NAMED_LITERAL_STRING(kOsVersion, "osversion");
437 191636 : NS_NAMED_LITERAL_STRING(kABI, "abi");
438 : #if defined(MOZ_WIDGET_ANDROID)
439 : NS_NAMED_LITERAL_STRING(kTablet, "tablet");
440 : #endif
441 :
442 : // Obsolete
443 191636 : NS_NAMED_LITERAL_STRING(kXPCNativeWrappers, "xpcnativewrappers");
444 :
445 191636 : nsAutoString appID;
446 191636 : nsAutoString appVersion;
447 191636 : nsAutoString geckoVersion;
448 191636 : nsAutoString osTarget;
449 191636 : nsAutoString abi;
450 :
451 191636 : nsCOMPtr<nsIXULAppInfo> xapp (do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
452 95818 : if (xapp) {
453 24302 : nsCAutoString s;
454 12151 : rv = xapp->GetID(s);
455 12151 : if (NS_SUCCEEDED(rv))
456 12151 : CopyUTF8toUTF16(s, appID);
457 :
458 12151 : rv = xapp->GetVersion(s);
459 12151 : if (NS_SUCCEEDED(rv))
460 12151 : CopyUTF8toUTF16(s, appVersion);
461 :
462 12151 : rv = xapp->GetPlatformVersion(s);
463 12151 : if (NS_SUCCEEDED(rv))
464 12151 : CopyUTF8toUTF16(s, geckoVersion);
465 :
466 24302 : nsCOMPtr<nsIXULRuntime> xruntime (do_QueryInterface(xapp));
467 12151 : if (xruntime) {
468 12151 : rv = xruntime->GetOS(s);
469 12151 : if (NS_SUCCEEDED(rv)) {
470 12151 : ToLowerCase(s);
471 12151 : CopyUTF8toUTF16(s, osTarget);
472 : }
473 :
474 12151 : rv = xruntime->GetXPCOMABI(s);
475 12151 : if (NS_SUCCEEDED(rv) && osTarget.Length()) {
476 12151 : ToLowerCase(s);
477 12151 : CopyUTF8toUTF16(s, abi);
478 12151 : abi.Insert(PRUnichar('_'), 0);
479 12151 : abi.Insert(osTarget, 0);
480 : }
481 : }
482 : }
483 :
484 191636 : nsAutoString osVersion;
485 : #if defined(XP_WIN)
486 : OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
487 : if (GetVersionEx(&info)) {
488 : nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
489 : info.dwMajorVersion,
490 : info.dwMinorVersion);
491 : }
492 : #elif defined(MOZ_WIDGET_COCOA)
493 : SInt32 majorVersion, minorVersion;
494 : if ((Gestalt(gestaltSystemVersionMajor, &majorVersion) == noErr) &&
495 : (Gestalt(gestaltSystemVersionMinor, &minorVersion) == noErr)) {
496 : nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
497 : majorVersion,
498 : minorVersion);
499 : }
500 : #elif defined(MOZ_WIDGET_GTK2)
501 95818 : nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
502 : gtk_major_version,
503 95818 : gtk_minor_version);
504 : #elif defined(MOZ_WIDGET_ANDROID)
505 : bool isTablet = false;
506 : if (mozilla::AndroidBridge::Bridge()) {
507 : mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", osVersion);
508 : isTablet = mozilla::AndroidBridge::Bridge()->IsTablet();
509 : }
510 : #endif
511 :
512 : // Because contracts must be registered after CIDs, we save and process them
513 : // at the end.
514 191636 : nsTArray<CachedDirective> contracts;
515 :
516 : char *token;
517 95818 : char *newline = buf;
518 95818 : PRUint32 line = 0;
519 :
520 : // outer loop tokenizes by newline
521 1025575 : while (*newline) {
522 1702507 : while (*newline && IsNewline(*newline)) {
523 22049 : ++newline;
524 22049 : ++line;
525 : }
526 840229 : if (!*newline)
527 6290 : break;
528 :
529 833939 : token = newline;
530 51523147 : while (*newline && !IsNewline(*newline))
531 49855269 : ++newline;
532 :
533 833939 : if (*newline) {
534 827658 : *newline = '\0';
535 827658 : ++newline;
536 : }
537 833939 : ++line;
538 :
539 833939 : if (*token == '#') // ignore lines that begin with # as comments
540 12610 : continue;
541 :
542 821329 : char *whitespace = token;
543 821329 : token = nsCRT::strtok(whitespace, kWhitespace, &whitespace);
544 821329 : if (!token) continue;
545 :
546 821329 : const ManifestDirective* directive = NULL;
547 6952002 : for (const ManifestDirective* d = kParsingTable;
548 3476001 : d < ArrayEnd(kParsingTable);
549 : ++d) {
550 3476001 : if (!strcmp(d->directive, token)) {
551 821329 : directive = d;
552 821329 : break;
553 : }
554 : }
555 :
556 821329 : if (!directive) {
557 : LogMessageWithContext(file, line,
558 : "Ignoring unrecognized chrome manifest directive '%s'.",
559 0 : token);
560 0 : continue;
561 : }
562 :
563 821329 : if (!directive->allowbootstrap && NS_BOOTSTRAPPED_LOCATION == type) {
564 : LogMessageWithContext(file, line,
565 : "Bootstrapped manifest not allowed to use '%s' directive.",
566 4 : token);
567 4 : continue;
568 : }
569 :
570 821325 : if (directive->componentonly && NS_SKIN_LOCATION == type) {
571 : LogMessageWithContext(file, line,
572 : "Skin manifest not allowed to use '%s' directive.",
573 0 : token);
574 0 : continue;
575 : }
576 :
577 821325 : NS_ASSERTION(directive->argc < 4, "Need to reset argv array length");
578 : char* argv[4];
579 2220657 : for (int i = 0; i < directive->argc; ++i)
580 1399332 : argv[i] = nsCRT::strtok(whitespace, kWhitespace, &whitespace);
581 :
582 821325 : if (!argv[directive->argc - 1]) {
583 : LogMessageWithContext(file, line,
584 : "Not enough arguments for chrome manifest directive '%s', expected %i.",
585 2 : token, directive->argc);
586 2 : continue;
587 : }
588 :
589 821323 : bool ok = true;
590 821323 : TriState stAppVersion = eUnspecified;
591 821323 : TriState stGeckoVersion = eUnspecified;
592 821323 : TriState stApp = eUnspecified;
593 821323 : TriState stOsVersion = eUnspecified;
594 821323 : TriState stOs = eUnspecified;
595 821323 : TriState stABI = eUnspecified;
596 : #if defined(MOZ_WIDGET_ANDROID)
597 : TriState stTablet = eUnspecified;
598 : #endif
599 821323 : bool platform = false;
600 821323 : bool contentAccessible = false;
601 :
602 1694511 : while (NULL != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && ok) {
603 51865 : ToLowerCase(token);
604 103730 : NS_ConvertASCIItoUTF16 wtoken(token);
605 :
606 99123 : if (CheckStringFlag(kApplication, wtoken, appID, stApp) ||
607 15742 : CheckStringFlag(kOs, wtoken, osTarget, stOs) ||
608 9456 : CheckStringFlag(kABI, wtoken, abi, stABI) ||
609 9452 : CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) ||
610 6312 : CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) ||
611 6296 : CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, stGeckoVersion))
612 45569 : continue;
613 :
614 : #if defined(MOZ_WIDGET_ANDROID)
615 : bool tablet = false;
616 : if (CheckFlag(kTablet, wtoken, tablet)) {
617 : stTablet = (tablet == isTablet) ? eOK : eBad;
618 : continue;
619 : }
620 : #endif
621 :
622 17318 : if (directive->contentflags &&
623 6296 : (CheckFlag(kPlatform, wtoken, platform) ||
624 4726 : CheckFlag(kContentAccessible, wtoken, contentAccessible)))
625 6286 : continue;
626 :
627 10 : bool xpcNativeWrappers = true; // Dummy for CheckFlag.
628 10 : if (CheckFlag(kXPCNativeWrappers, wtoken, xpcNativeWrappers)) {
629 : LogMessageWithContext(file, line,
630 : "Ignoring obsolete chrome registration modifier '%s'.",
631 0 : token);
632 0 : continue;
633 : }
634 :
635 : LogMessageWithContext(file, line,
636 : "Unrecognized chrome manifest modifier '%s'.",
637 10 : token);
638 10 : ok = false;
639 : }
640 :
641 821323 : if (!ok ||
642 : stApp == eBad ||
643 : stAppVersion == eBad ||
644 : stGeckoVersion == eBad ||
645 : stOs == eBad ||
646 : stOsVersion == eBad ||
647 : #ifdef MOZ_WIDGET_ANDROID
648 : stTablet == eBad ||
649 : #endif
650 : stABI == eBad)
651 39283 : continue;
652 :
653 782040 : if (directive->regfunc) {
654 83321 : if (GeckoProcessType_Default != XRE_GetProcessType())
655 0 : continue;
656 :
657 83321 : if (!nsChromeRegistry::gChromeRegistry) {
658 : nsCOMPtr<nsIChromeRegistry> cr =
659 2730 : mozilla::services::GetChromeRegistryService();
660 1365 : if (!nsChromeRegistry::gChromeRegistry) {
661 : LogMessageWithContext(file, line,
662 0 : "Chrome registry isn't available yet.");
663 0 : continue;
664 : }
665 : }
666 :
667 : (nsChromeRegistry::gChromeRegistry->*(directive->regfunc))
668 83321 : (chromecx, line, argv, platform, contentAccessible);
669 : }
670 698719 : else if (directive->ischrome || !aChromeOnly) {
671 619589 : if (directive->isContract) {
672 132427 : CachedDirective* cd = contracts.AppendElement();
673 132427 : cd->lineno = line;
674 132427 : cd->argv[0] = argv[0];
675 132427 : cd->argv[1] = argv[1];
676 : }
677 : else
678 : (nsComponentManagerImpl::gComponentManager->*(directive->mgrfunc))
679 487162 : (mgrcx, line, argv);
680 : }
681 : }
682 :
683 228245 : for (PRUint32 i = 0; i < contracts.Length(); ++i) {
684 132427 : CachedDirective& d = contracts[i];
685 : nsComponentManagerImpl::gComponentManager->ManifestContract
686 132427 : (mgrcx, d.lineno, d.argv);
687 : }
688 95818 : }
|