LCOV - code coverage report
Current view: top level - xpcom/components - ManifestParser.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 89 255 34.9 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.13-14-ga5dd952