LCOV - code coverage report
Current view: directory - xpcom/components - ManifestParser.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 249 233 93.6 %
Date: 2012-06-02 Functions: 12 12 100.0 %

       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        53306398 : static bool IsNewline(char c)
     134                 : {
     135        53306398 :   return c == '\n' || c == '\r';
     136                 : }
     137                 : 
     138                 : namespace {
     139                 : struct AutoPR_smprintf_free
     140                 : {
     141            1408 :   AutoPR_smprintf_free(char* buf)
     142            1408 :     : mBuf(buf)
     143                 :   {
     144            1408 :   }
     145                 : 
     146            1408 :   ~AutoPR_smprintf_free()
     147                 :   {
     148            1408 :     if (mBuf)
     149            1408 :       PR_smprintf_free(mBuf);
     150            1408 :   }
     151                 : 
     152            2815 :   operator char*() const {
     153            2815 :     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            1407 : void LogMessageWithContext(FileLocation &aFile,
     179                 :                            PRUint32 aLineNumber, const char* aMsg, ...)
     180                 : {
     181                 :   va_list args;
     182            1407 :   va_start(args, aMsg);
     183            2814 :   AutoPR_smprintf_free formatted(PR_vsmprintf(aMsg, args));
     184            1407 :   va_end(args);
     185            1407 :   if (!formatted)
     186                 :     return;
     187                 : 
     188            2814 :   nsCString file;
     189            1407 :   aFile.GetURIString(file);
     190                 : 
     191                 :   nsCOMPtr<nsIScriptError> error =
     192            2814 :     do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
     193            1407 :   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            2814 :     do_GetService(NS_CONSOLESERVICE_CONTRACTID);
     203            1407 :   if (!console)
     204                 :     return;
     205                 : 
     206            4221 :   nsresult rv = error->Init(NS_ConvertUTF8toUTF16(formatted).get(),
     207            1407 :                             NS_ConvertUTF8toUTF16(file).get(), NULL,
     208                 :                             aLineNumber, 0, nsIScriptError::warningFlag,
     209            2814 :                             "chrome registration");
     210            1407 :   if (NS_FAILED(rv))
     211                 :     return;
     212                 : 
     213            2814 :   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           11410 : CheckFlag(const nsSubstring& aFlag, const nsSubstring& aData, bool& aResult)
     229                 : {
     230           11410 :   if (!StringBeginsWith(aData, aFlag))
     231            4908 :     return false;
     232                 : 
     233            6502 :   if (aFlag.Length() == aData.Length()) {
     234                 :     // the data is simply "flag", which is the same as "flag=yes"
     235            1626 :     aResult = true;
     236            1626 :     return true;
     237                 :   }
     238                 : 
     239            4876 :   if (aData.CharAt(aFlag.Length()) != '=') {
     240                 :     // the data is "flag2=", which is not anything we care about
     241               0 :     return false;
     242                 :   }
     243                 : 
     244            4876 :   if (aData.Length() == aFlag.Length() + 1) {
     245               0 :     aResult = false;
     246               0 :     return true;
     247                 :   }
     248                 : 
     249            4876 :   switch (aData.CharAt(aFlag.Length() + 1)) {
     250                 :   case '1':
     251                 :   case 't': //true
     252                 :   case 'y': //yes
     253            4874 :     aResult = true;
     254            4874 :     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           79709 : CheckStringFlag(const nsSubstring& aFlag, const nsSubstring& aData,
     286                 :                 const nsSubstring& aValue, TriState& aResult)
     287                 : {
     288           79709 :   if (aData.Length() < aFlag.Length() + 1)
     289           11382 :     return false;
     290                 : 
     291           68327 :   if (!StringBeginsWith(aData, aFlag))
     292           21206 :     return false;
     293                 : 
     294           47121 :   bool comparison = true;
     295           47121 :   if (aData[aFlag.Length()] != '=') {
     296           13022 :     if (aData[aFlag.Length()] == '!' &&
     297            3258 :         aData.Length() >= aFlag.Length() + 2 &&
     298            3258 :         aData[aFlag.Length() + 1] == '=')
     299            3256 :       comparison = false;
     300                 :     else
     301            3250 :       return false;
     302                 :   }
     303                 : 
     304           43871 :   if (aResult != eOK) {
     305           87742 :     nsDependentSubstring testdata = Substring(aData, aFlag.Length() + (comparison ? 1 : 2));
     306           43871 :     if (testdata.Equals(aValue))
     307               9 :       aResult = comparison ? eOK : eBad;
     308                 :     else
     309           43862 :       aResult = comparison ? eBad : eOK;
     310                 :   }
     311                 : 
     312           43871 :   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           22816 : CheckVersionFlag(const nsString& aFlag, const nsString& aData,
     338                 :                  const nsString& aValue, TriState& aResult)
     339                 : {
     340           22816 :   if (aData.Length() < aFlag.Length() + 2)
     341            4890 :     return false;
     342                 : 
     343           17926 :   if (!StringBeginsWith(aData, aFlag))
     344           14662 :     return false;
     345                 : 
     346            3264 :   if (aValue.Length() == 0) {
     347               8 :     if (aResult != eOK)
     348               8 :       aResult = eBad;
     349               8 :     return true;
     350                 :   }
     351                 : 
     352                 :   PRUint32 comparison;
     353            6512 :   nsAutoString testdata;
     354                 : 
     355            3256 :   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            3251 :     if (aData[aFlag.Length() + 1] == '=') {
     363               1 :       comparison = COMPARE_EQ | COMPARE_LT;
     364               1 :       testdata = Substring(aData, aFlag.Length() + 2);
     365                 :     }
     366                 :     else {
     367            3250 :       comparison = COMPARE_LT;
     368            3250 :       testdata = Substring(aData, aFlag.Length() + 1);
     369                 :     }
     370            3251 :     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            3256 :   if (testdata.Length() == 0)
     388               0 :     return false;
     389                 : 
     390            3256 :   if (aResult != eOK) {
     391            3256 :     PRInt32 c = NS_CompareVersions(NS_ConvertUTF16toUTF8(aValue).get(),
     392            6512 :                                    NS_ConvertUTF16toUTF8(testdata).get());
     393            3256 :     if ((c == 0 && comparison & COMPARE_EQ) ||
     394                 :         (c < 0 && comparison & COMPARE_LT) ||
     395                 :         (c > 0 && comparison & COMPARE_GT))
     396            3253 :       aResult = eOK;
     397                 :     else
     398               3 :       aResult = eBad;
     399                 :   }
     400                 : 
     401            3256 :   return true;
     402                 : }
     403                 : 
     404                 : // In-place conversion of ascii characters to lower case
     405                 : static void
     406           53647 : ToLowerCase(char* token)
     407                 : {
     408         2128765 :   for (; *token; ++token)
     409         2075118 :     *token = NS_ToLower(*token);
     410           53647 : }
     411                 : 
     412                 : namespace {
     413                 : 
     414                 : struct CachedDirective
     415          137637 : {
     416                 :   int lineno;
     417                 :   char* argv[4];
     418                 : };
     419                 : 
     420                 : } // anonymous namespace
     421                 : 
     422                 : 
     423                 : void
     424           99082 : ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOnly)
     425                 : {
     426          198164 :   nsComponentManagerImpl::ManifestProcessingContext mgrcx(type, file, aChromeOnly);
     427          198164 :   nsChromeRegistry::ManifestProcessingContext chromecx(type, file);
     428                 :   nsresult rv;
     429                 : 
     430          198164 :   NS_NAMED_LITERAL_STRING(kPlatform, "platform");
     431          198164 :   NS_NAMED_LITERAL_STRING(kContentAccessible, "contentaccessible");
     432          198164 :   NS_NAMED_LITERAL_STRING(kApplication, "application");
     433          198164 :   NS_NAMED_LITERAL_STRING(kAppVersion, "appversion");
     434          198164 :   NS_NAMED_LITERAL_STRING(kGeckoVersion, "platformversion");
     435          198164 :   NS_NAMED_LITERAL_STRING(kOs, "os");
     436          198164 :   NS_NAMED_LITERAL_STRING(kOsVersion, "osversion");
     437          198164 :   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          198164 :   NS_NAMED_LITERAL_STRING(kXPCNativeWrappers, "xpcnativewrappers");
     444                 : 
     445          198164 :   nsAutoString appID;
     446          198164 :   nsAutoString appVersion;
     447          198164 :   nsAutoString geckoVersion;
     448          198164 :   nsAutoString osTarget;
     449          198164 :   nsAutoString abi;
     450                 : 
     451          198164 :   nsCOMPtr<nsIXULAppInfo> xapp (do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
     452           99082 :   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          198164 :   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           99082 :   nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
     502                 :                                        gtk_major_version,
     503           99082 :                                        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          198164 :   nsTArray<CachedDirective> contracts;
     515                 : 
     516                 :   char *token;
     517           99082 :   char *newline = buf;
     518           99082 :   PRUint32 line = 0;
     519                 : 
     520                 :   // outer loop tokenizes by newline
     521         1060688 :   while (*newline) {
     522         1760866 :     while (*newline && IsNewline(*newline)) {
     523           22806 :       ++newline;
     524           22806 :       ++line;
     525                 :     }
     526          869030 :     if (!*newline)
     527            6506 :       break;
     528                 : 
     529          862524 :     token = newline;
     530        53290089 :     while (*newline && !IsNewline(*newline))
     531        51565041 :       ++newline;
     532                 : 
     533          862524 :     if (*newline) {
     534          856027 :       *newline = '\0';
     535          856027 :       ++newline;
     536                 :     }
     537          862524 :     ++line;
     538                 : 
     539          862524 :     if (*token == '#') // ignore lines that begin with # as comments
     540           13042 :       continue;
     541                 : 
     542          849482 :     char *whitespace = token;
     543          849482 :     token = nsCRT::strtok(whitespace, kWhitespace, &whitespace);
     544          849482 :     if (!token) continue;
     545                 : 
     546          849482 :     const ManifestDirective* directive = NULL;
     547         7190302 :     for (const ManifestDirective* d = kParsingTable;
     548         3595151 :          d < ArrayEnd(kParsingTable);
     549                 :          ++d) {
     550         3595151 :       if (!strcmp(d->directive, token)) {
     551          849482 :         directive = d;
     552          849482 :         break;
     553                 :       }
     554                 :     }
     555                 : 
     556          849482 :     if (!directive) {
     557                 :       LogMessageWithContext(file, line,
     558                 :                             "Ignoring unrecognized chrome manifest directive '%s'.",
     559               0 :                             token);
     560               0 :       continue;
     561                 :     }
     562                 : 
     563          849482 :     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          849478 :     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          849478 :     NS_ASSERTION(directive->argc < 4, "Need to reset argv array length");
     578                 :     char* argv[4];
     579         2296779 :     for (int i = 0; i < directive->argc; ++i)
     580         1447301 :       argv[i] = nsCRT::strtok(whitespace, kWhitespace, &whitespace);
     581                 : 
     582          849478 :     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          849476 :     bool ok = true;
     590          849476 :     TriState stAppVersion = eUnspecified;
     591          849476 :     TriState stGeckoVersion = eUnspecified;
     592          849476 :     TriState stApp = eUnspecified;
     593          849476 :     TriState stOsVersion = eUnspecified;
     594          849476 :     TriState stOs = eUnspecified;
     595          849476 :     TriState stABI = eUnspecified;
     596                 : #if defined(MOZ_WIDGET_ANDROID)
     597                 :     TriState stTablet = eUnspecified;
     598                 : #endif
     599          849476 :     bool platform = false;
     600          849476 :     bool contentAccessible = false;
     601                 : 
     602         1752599 :     while (NULL != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && ok) {
     603           53647 :       ToLowerCase(token);
     604          107294 :       NS_ConvertASCIItoUTF16 wtoken(token);
     605                 : 
     606          102525 :       if (CheckStringFlag(kApplication, wtoken, appID, stApp) ||
     607           16282 :           CheckStringFlag(kOs, wtoken, osTarget, stOs) ||
     608            9780 :           CheckStringFlag(kABI, wtoken, abi, stABI) ||
     609            9776 :           CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) ||
     610            6528 :           CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) ||
     611            6512 :           CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, stGeckoVersion))
     612           47135 :         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           17912 :       if (directive->contentflags &&
     623            6512 :           (CheckFlag(kPlatform, wtoken, platform) ||
     624            4888 :            CheckFlag(kContentAccessible, wtoken, contentAccessible)))
     625            6502 :         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          849476 :     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           40633 :       continue;
     652                 : 
     653          808843 :     if (directive->regfunc) {
     654           86183 :       if (GeckoProcessType_Default != XRE_GetProcessType())
     655               0 :         continue;
     656                 : 
     657           86183 :       if (!nsChromeRegistry::gChromeRegistry) {
     658                 :         nsCOMPtr<nsIChromeRegistry> cr =
     659            2838 :           mozilla::services::GetChromeRegistryService();
     660            1419 :         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           86183 :         (chromecx, line, argv, platform, contentAccessible);
     669                 :     }
     670          722660 :     else if (directive->ischrome || !aChromeOnly) {
     671          643530 :       if (directive->isContract) {
     672          137637 :         CachedDirective* cd = contracts.AppendElement();
     673          137637 :         cd->lineno = line;
     674          137637 :         cd->argv[0] = argv[0];
     675          137637 :         cd->argv[1] = argv[1];
     676                 :       }
     677                 :       else
     678                 :         (nsComponentManagerImpl::gComponentManager->*(directive->mgrfunc))
     679          505893 :           (mgrcx, line, argv);
     680                 :     }
     681                 :   }
     682                 : 
     683          236719 :   for (PRUint32 i = 0; i < contracts.Length(); ++i) {
     684          137637 :     CachedDirective& d = contracts[i];
     685                 :     nsComponentManagerImpl::gComponentManager->ManifestContract
     686          137637 :       (mgrcx, d.lineno, d.argv);
     687                 :   }
     688           99082 : }

Generated by: LCOV version 1.7