1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/components/ManifestParser.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,657 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "mozilla/ArrayUtils.h" 1.10 + 1.11 +#include "ManifestParser.h" 1.12 + 1.13 +#include <string.h> 1.14 + 1.15 +#include "prio.h" 1.16 +#include "prprf.h" 1.17 +#if defined(XP_WIN) 1.18 +#include <windows.h> 1.19 +#elif defined(MOZ_WIDGET_COCOA) 1.20 +#include <CoreServices/CoreServices.h> 1.21 +#include "nsCocoaFeatures.h" 1.22 +#elif defined(MOZ_WIDGET_GTK) 1.23 +#include <gtk/gtk.h> 1.24 +#endif 1.25 + 1.26 +#ifdef MOZ_WIDGET_ANDROID 1.27 +#include "AndroidBridge.h" 1.28 +#endif 1.29 + 1.30 +#include "mozilla/Services.h" 1.31 + 1.32 +#include "nsCRT.h" 1.33 +#include "nsConsoleMessage.h" 1.34 +#include "nsTextFormatter.h" 1.35 +#include "nsVersionComparator.h" 1.36 +#include "nsXPCOMCIDInternal.h" 1.37 + 1.38 +#include "nsIConsoleService.h" 1.39 +#include "nsIScriptError.h" 1.40 +#include "nsIXULAppInfo.h" 1.41 +#include "nsIXULRuntime.h" 1.42 + 1.43 +using namespace mozilla; 1.44 + 1.45 +struct ManifestDirective 1.46 +{ 1.47 + const char* directive; 1.48 + int argc; 1.49 + 1.50 + // Some directives should only be delivered for NS_COMPONENT_LOCATION 1.51 + // manifests. 1.52 + bool componentonly; 1.53 + 1.54 + bool ischrome; 1.55 + 1.56 + bool allowbootstrap; 1.57 + 1.58 + // The platform/contentaccessible flags only apply to content directives. 1.59 + bool contentflags; 1.60 + 1.61 + // Function to handle this directive. This isn't a union because C++ still 1.62 + // hasn't learned how to initialize unions in a sane way. 1.63 + void (nsComponentManagerImpl::*mgrfunc) 1.64 + (nsComponentManagerImpl::ManifestProcessingContext& cx, 1.65 + int lineno, char *const * argv); 1.66 + void (nsChromeRegistry::*regfunc) 1.67 + (nsChromeRegistry::ManifestProcessingContext& cx, 1.68 + int lineno, char *const *argv, 1.69 + bool platform, bool contentaccessible); 1.70 + 1.71 + bool isContract; 1.72 +}; 1.73 +static const ManifestDirective kParsingTable[] = { 1.74 + { "manifest", 1, false, true, true, false, 1.75 + &nsComponentManagerImpl::ManifestManifest, nullptr }, 1.76 + { "binary-component", 1, true, false, false, false, 1.77 + &nsComponentManagerImpl::ManifestBinaryComponent, nullptr }, 1.78 + { "interfaces", 1, true, false, false, false, 1.79 + &nsComponentManagerImpl::ManifestXPT, nullptr }, 1.80 + { "component", 2, true, false, false, false, 1.81 + &nsComponentManagerImpl::ManifestComponent, nullptr }, 1.82 + { "contract", 2, true, false, false, false, 1.83 + &nsComponentManagerImpl::ManifestContract, nullptr, true}, 1.84 + { "category", 3, true, false, false, false, 1.85 + &nsComponentManagerImpl::ManifestCategory, nullptr }, 1.86 + { "content", 2, true, true, true, true, 1.87 + nullptr, &nsChromeRegistry::ManifestContent }, 1.88 + { "locale", 3, true, true, true, false, 1.89 + nullptr, &nsChromeRegistry::ManifestLocale }, 1.90 + { "skin", 3, false, true, true, false, 1.91 + nullptr, &nsChromeRegistry::ManifestSkin }, 1.92 + { "overlay", 2, true, true, false, false, 1.93 + nullptr, &nsChromeRegistry::ManifestOverlay }, 1.94 + { "style", 2, false, true, false, false, 1.95 + nullptr, &nsChromeRegistry::ManifestStyle }, 1.96 + { "override", 2, true, true, true, false, 1.97 + nullptr, &nsChromeRegistry::ManifestOverride }, 1.98 + { "resource", 2, true, true, false, false, 1.99 + nullptr, &nsChromeRegistry::ManifestResource } 1.100 +}; 1.101 + 1.102 +static const char kWhitespace[] = "\t "; 1.103 + 1.104 +static bool IsNewline(char c) 1.105 +{ 1.106 + return c == '\n' || c == '\r'; 1.107 +} 1.108 + 1.109 +namespace { 1.110 +struct AutoPR_smprintf_free 1.111 +{ 1.112 + AutoPR_smprintf_free(char* buf) 1.113 + : mBuf(buf) 1.114 + { 1.115 + } 1.116 + 1.117 + ~AutoPR_smprintf_free() 1.118 + { 1.119 + if (mBuf) 1.120 + PR_smprintf_free(mBuf); 1.121 + } 1.122 + 1.123 + operator char*() const { 1.124 + return mBuf; 1.125 + } 1.126 + 1.127 + char* mBuf; 1.128 +}; 1.129 + 1.130 +} // anonymous namespace 1.131 + 1.132 +void LogMessage(const char* aMsg, ...) 1.133 +{ 1.134 + nsCOMPtr<nsIConsoleService> console = 1.135 + do_GetService(NS_CONSOLESERVICE_CONTRACTID); 1.136 + if (!console) 1.137 + return; 1.138 + 1.139 + va_list args; 1.140 + va_start(args, aMsg); 1.141 + AutoPR_smprintf_free formatted(PR_vsmprintf(aMsg, args)); 1.142 + va_end(args); 1.143 + 1.144 + nsCOMPtr<nsIConsoleMessage> error = 1.145 + new nsConsoleMessage(NS_ConvertUTF8toUTF16(formatted).get()); 1.146 + console->LogMessage(error); 1.147 +} 1.148 + 1.149 +void LogMessageWithContext(FileLocation &aFile, 1.150 + uint32_t aLineNumber, const char* aMsg, ...) 1.151 +{ 1.152 + va_list args; 1.153 + va_start(args, aMsg); 1.154 + AutoPR_smprintf_free formatted(PR_vsmprintf(aMsg, args)); 1.155 + va_end(args); 1.156 + if (!formatted) 1.157 + return; 1.158 + 1.159 + nsCString file; 1.160 + aFile.GetURIString(file); 1.161 + 1.162 + nsCOMPtr<nsIScriptError> error = 1.163 + do_CreateInstance(NS_SCRIPTERROR_CONTRACTID); 1.164 + if (!error) { 1.165 + // This can happen early in component registration. Fall back to a 1.166 + // generic console message. 1.167 + LogMessage("Warning: in '%s', line %i: %s", file.get(), 1.168 + aLineNumber, (char*) formatted); 1.169 + return; 1.170 + } 1.171 + 1.172 + nsCOMPtr<nsIConsoleService> console = 1.173 + do_GetService(NS_CONSOLESERVICE_CONTRACTID); 1.174 + if (!console) 1.175 + return; 1.176 + 1.177 + nsresult rv = error->Init(NS_ConvertUTF8toUTF16(formatted), 1.178 + NS_ConvertUTF8toUTF16(file), EmptyString(), 1.179 + aLineNumber, 0, nsIScriptError::warningFlag, 1.180 + "chrome registration"); 1.181 + if (NS_FAILED(rv)) 1.182 + return; 1.183 + 1.184 + console->LogMessage(error); 1.185 +} 1.186 + 1.187 +/** 1.188 + * Check for a modifier flag of the following forms: 1.189 + * "flag" (same as "true") 1.190 + * "flag=yes|true|1" 1.191 + * "flag="no|false|0" 1.192 + * @param aFlag The flag to compare. 1.193 + * @param aData The tokenized data to check; this is lowercased 1.194 + * before being passed in. 1.195 + * @param aResult If the flag is found, the value is assigned here. 1.196 + * @return Whether the flag was handled. 1.197 + */ 1.198 +static bool 1.199 +CheckFlag(const nsSubstring& aFlag, const nsSubstring& aData, bool& aResult) 1.200 +{ 1.201 + if (!StringBeginsWith(aData, aFlag)) 1.202 + return false; 1.203 + 1.204 + if (aFlag.Length() == aData.Length()) { 1.205 + // the data is simply "flag", which is the same as "flag=yes" 1.206 + aResult = true; 1.207 + return true; 1.208 + } 1.209 + 1.210 + if (aData.CharAt(aFlag.Length()) != '=') { 1.211 + // the data is "flag2=", which is not anything we care about 1.212 + return false; 1.213 + } 1.214 + 1.215 + if (aData.Length() == aFlag.Length() + 1) { 1.216 + aResult = false; 1.217 + return true; 1.218 + } 1.219 + 1.220 + switch (aData.CharAt(aFlag.Length() + 1)) { 1.221 + case '1': 1.222 + case 't': //true 1.223 + case 'y': //yes 1.224 + aResult = true; 1.225 + return true; 1.226 + 1.227 + case '0': 1.228 + case 'f': //false 1.229 + case 'n': //no 1.230 + aResult = false; 1.231 + return true; 1.232 + } 1.233 + 1.234 + return false; 1.235 +} 1.236 + 1.237 +enum TriState { 1.238 + eUnspecified, 1.239 + eBad, 1.240 + eOK 1.241 +}; 1.242 + 1.243 +/** 1.244 + * Check for a modifier flag of the following form: 1.245 + * "flag=string" 1.246 + * "flag!=string" 1.247 + * @param aFlag The flag to compare. 1.248 + * @param aData The tokenized data to check; this is lowercased 1.249 + * before being passed in. 1.250 + * @param aValue The value that is expected. 1.251 + * @param aResult If this is "ok" when passed in, this is left alone. 1.252 + * Otherwise if the flag is found it is set to eBad or eOK. 1.253 + * @return Whether the flag was handled. 1.254 + */ 1.255 +static bool 1.256 +CheckStringFlag(const nsSubstring& aFlag, const nsSubstring& aData, 1.257 + const nsSubstring& aValue, TriState& aResult) 1.258 +{ 1.259 + if (aData.Length() < aFlag.Length() + 1) 1.260 + return false; 1.261 + 1.262 + if (!StringBeginsWith(aData, aFlag)) 1.263 + return false; 1.264 + 1.265 + bool comparison = true; 1.266 + if (aData[aFlag.Length()] != '=') { 1.267 + if (aData[aFlag.Length()] == '!' && 1.268 + aData.Length() >= aFlag.Length() + 2 && 1.269 + aData[aFlag.Length() + 1] == '=') 1.270 + comparison = false; 1.271 + else 1.272 + return false; 1.273 + } 1.274 + 1.275 + if (aResult != eOK) { 1.276 + nsDependentSubstring testdata = Substring(aData, aFlag.Length() + (comparison ? 1 : 2)); 1.277 + if (testdata.Equals(aValue)) 1.278 + aResult = comparison ? eOK : eBad; 1.279 + else 1.280 + aResult = comparison ? eBad : eOK; 1.281 + } 1.282 + 1.283 + return true; 1.284 +} 1.285 + 1.286 +/** 1.287 + * Check for a modifier flag of the following form: 1.288 + * "flag=version" 1.289 + * "flag<=version" 1.290 + * "flag<version" 1.291 + * "flag>=version" 1.292 + * "flag>version" 1.293 + * @param aFlag The flag to compare. 1.294 + * @param aData The tokenized data to check; this is lowercased 1.295 + * before being passed in. 1.296 + * @param aValue The value that is expected. If this is empty then no 1.297 + * comparison will match. 1.298 + * @param aResult If this is eOK when passed in, this is left alone. 1.299 + * Otherwise if the flag is found it is set to eBad or eOK. 1.300 + * @return Whether the flag was handled. 1.301 + */ 1.302 + 1.303 +#define COMPARE_EQ 1 << 0 1.304 +#define COMPARE_LT 1 << 1 1.305 +#define COMPARE_GT 1 << 2 1.306 + 1.307 +static bool 1.308 +CheckVersionFlag(const nsString& aFlag, const nsString& aData, 1.309 + const nsString& aValue, TriState& aResult) 1.310 +{ 1.311 + if (aData.Length() < aFlag.Length() + 2) 1.312 + return false; 1.313 + 1.314 + if (!StringBeginsWith(aData, aFlag)) 1.315 + return false; 1.316 + 1.317 + if (aValue.Length() == 0) { 1.318 + if (aResult != eOK) 1.319 + aResult = eBad; 1.320 + return true; 1.321 + } 1.322 + 1.323 + uint32_t comparison; 1.324 + nsAutoString testdata; 1.325 + 1.326 + switch (aData[aFlag.Length()]) { 1.327 + case '=': 1.328 + comparison = COMPARE_EQ; 1.329 + testdata = Substring(aData, aFlag.Length() + 1); 1.330 + break; 1.331 + 1.332 + case '<': 1.333 + if (aData[aFlag.Length() + 1] == '=') { 1.334 + comparison = COMPARE_EQ | COMPARE_LT; 1.335 + testdata = Substring(aData, aFlag.Length() + 2); 1.336 + } 1.337 + else { 1.338 + comparison = COMPARE_LT; 1.339 + testdata = Substring(aData, aFlag.Length() + 1); 1.340 + } 1.341 + break; 1.342 + 1.343 + case '>': 1.344 + if (aData[aFlag.Length() + 1] == '=') { 1.345 + comparison = COMPARE_EQ | COMPARE_GT; 1.346 + testdata = Substring(aData, aFlag.Length() + 2); 1.347 + } 1.348 + else { 1.349 + comparison = COMPARE_GT; 1.350 + testdata = Substring(aData, aFlag.Length() + 1); 1.351 + } 1.352 + break; 1.353 + 1.354 + default: 1.355 + return false; 1.356 + } 1.357 + 1.358 + if (testdata.Length() == 0) 1.359 + return false; 1.360 + 1.361 + if (aResult != eOK) { 1.362 + int32_t c = mozilla::CompareVersions(NS_ConvertUTF16toUTF8(aValue).get(), 1.363 + NS_ConvertUTF16toUTF8(testdata).get()); 1.364 + if ((c == 0 && comparison & COMPARE_EQ) || 1.365 + (c < 0 && comparison & COMPARE_LT) || 1.366 + (c > 0 && comparison & COMPARE_GT)) 1.367 + aResult = eOK; 1.368 + else 1.369 + aResult = eBad; 1.370 + } 1.371 + 1.372 + return true; 1.373 +} 1.374 + 1.375 +// In-place conversion of ascii characters to lower case 1.376 +static void 1.377 +ToLowerCase(char* token) 1.378 +{ 1.379 + for (; *token; ++token) 1.380 + *token = NS_ToLower(*token); 1.381 +} 1.382 + 1.383 +namespace { 1.384 + 1.385 +struct CachedDirective 1.386 +{ 1.387 + int lineno; 1.388 + char* argv[4]; 1.389 +}; 1.390 + 1.391 +} // anonymous namespace 1.392 + 1.393 + 1.394 +void 1.395 +ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOnly) 1.396 +{ 1.397 + nsComponentManagerImpl::ManifestProcessingContext mgrcx(type, file, aChromeOnly); 1.398 + nsChromeRegistry::ManifestProcessingContext chromecx(type, file); 1.399 + nsresult rv; 1.400 + 1.401 + NS_NAMED_LITERAL_STRING(kPlatform, "platform"); 1.402 + NS_NAMED_LITERAL_STRING(kContentAccessible, "contentaccessible"); 1.403 + NS_NAMED_LITERAL_STRING(kApplication, "application"); 1.404 + NS_NAMED_LITERAL_STRING(kAppVersion, "appversion"); 1.405 + NS_NAMED_LITERAL_STRING(kGeckoVersion, "platformversion"); 1.406 + NS_NAMED_LITERAL_STRING(kOs, "os"); 1.407 + NS_NAMED_LITERAL_STRING(kOsVersion, "osversion"); 1.408 + NS_NAMED_LITERAL_STRING(kABI, "abi"); 1.409 +#if defined(MOZ_WIDGET_ANDROID) 1.410 + NS_NAMED_LITERAL_STRING(kTablet, "tablet"); 1.411 +#endif 1.412 + 1.413 + // Obsolete 1.414 + NS_NAMED_LITERAL_STRING(kXPCNativeWrappers, "xpcnativewrappers"); 1.415 + 1.416 + nsAutoString appID; 1.417 + nsAutoString appVersion; 1.418 + nsAutoString geckoVersion; 1.419 + nsAutoString osTarget; 1.420 + nsAutoString abi; 1.421 + 1.422 + nsCOMPtr<nsIXULAppInfo> xapp (do_GetService(XULAPPINFO_SERVICE_CONTRACTID)); 1.423 + if (xapp) { 1.424 + nsAutoCString s; 1.425 + rv = xapp->GetID(s); 1.426 + if (NS_SUCCEEDED(rv)) 1.427 + CopyUTF8toUTF16(s, appID); 1.428 + 1.429 + rv = xapp->GetVersion(s); 1.430 + if (NS_SUCCEEDED(rv)) 1.431 + CopyUTF8toUTF16(s, appVersion); 1.432 + 1.433 + rv = xapp->GetPlatformVersion(s); 1.434 + if (NS_SUCCEEDED(rv)) 1.435 + CopyUTF8toUTF16(s, geckoVersion); 1.436 + 1.437 + nsCOMPtr<nsIXULRuntime> xruntime (do_QueryInterface(xapp)); 1.438 + if (xruntime) { 1.439 + rv = xruntime->GetOS(s); 1.440 + if (NS_SUCCEEDED(rv)) { 1.441 + ToLowerCase(s); 1.442 + CopyUTF8toUTF16(s, osTarget); 1.443 + } 1.444 + 1.445 + rv = xruntime->GetXPCOMABI(s); 1.446 + if (NS_SUCCEEDED(rv) && osTarget.Length()) { 1.447 + ToLowerCase(s); 1.448 + CopyUTF8toUTF16(s, abi); 1.449 + abi.Insert(char16_t('_'), 0); 1.450 + abi.Insert(osTarget, 0); 1.451 + } 1.452 + } 1.453 + } 1.454 + 1.455 + nsAutoString osVersion; 1.456 +#if defined(XP_WIN) 1.457 +#pragma warning(push) 1.458 +#pragma warning(disable:4996) // VC12+ deprecates GetVersionEx 1.459 + OSVERSIONINFO info = { sizeof(OSVERSIONINFO) }; 1.460 + if (GetVersionEx(&info)) { 1.461 + nsTextFormatter::ssprintf(osVersion, MOZ_UTF16("%ld.%ld"), 1.462 + info.dwMajorVersion, 1.463 + info.dwMinorVersion); 1.464 + } 1.465 +#pragma warning(pop) 1.466 +#elif defined(MOZ_WIDGET_COCOA) 1.467 + SInt32 majorVersion = nsCocoaFeatures::OSXVersionMajor(); 1.468 + SInt32 minorVersion = nsCocoaFeatures::OSXVersionMinor(); 1.469 + nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(), 1.470 + majorVersion, 1.471 + minorVersion); 1.472 +#elif defined(MOZ_WIDGET_GTK) 1.473 + nsTextFormatter::ssprintf(osVersion, MOZ_UTF16("%ld.%ld"), 1.474 + gtk_major_version, 1.475 + gtk_minor_version); 1.476 +#elif defined(MOZ_WIDGET_ANDROID) 1.477 + bool isTablet = false; 1.478 + if (mozilla::AndroidBridge::Bridge()) { 1.479 + mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", osVersion); 1.480 + isTablet = mozilla::widget::android::GeckoAppShell::IsTablet(); 1.481 + } 1.482 +#endif 1.483 + 1.484 + // Because contracts must be registered after CIDs, we save and process them 1.485 + // at the end. 1.486 + nsTArray<CachedDirective> contracts; 1.487 + 1.488 + char *token; 1.489 + char *newline = buf; 1.490 + uint32_t line = 0; 1.491 + 1.492 + // outer loop tokenizes by newline 1.493 + while (*newline) { 1.494 + while (*newline && IsNewline(*newline)) { 1.495 + ++newline; 1.496 + ++line; 1.497 + } 1.498 + if (!*newline) 1.499 + break; 1.500 + 1.501 + token = newline; 1.502 + while (*newline && !IsNewline(*newline)) 1.503 + ++newline; 1.504 + 1.505 + if (*newline) { 1.506 + *newline = '\0'; 1.507 + ++newline; 1.508 + } 1.509 + ++line; 1.510 + 1.511 + if (*token == '#') // ignore lines that begin with # as comments 1.512 + continue; 1.513 + 1.514 + char *whitespace = token; 1.515 + token = nsCRT::strtok(whitespace, kWhitespace, &whitespace); 1.516 + if (!token) continue; 1.517 + 1.518 + const ManifestDirective* directive = nullptr; 1.519 + for (const ManifestDirective* d = kParsingTable; 1.520 + d < ArrayEnd(kParsingTable); 1.521 + ++d) { 1.522 + if (!strcmp(d->directive, token)) { 1.523 + directive = d; 1.524 + break; 1.525 + } 1.526 + } 1.527 + 1.528 + if (!directive) { 1.529 + LogMessageWithContext(file, line, 1.530 + "Ignoring unrecognized chrome manifest directive '%s'.", 1.531 + token); 1.532 + continue; 1.533 + } 1.534 + 1.535 + if (!directive->allowbootstrap && NS_BOOTSTRAPPED_LOCATION == type) { 1.536 + LogMessageWithContext(file, line, 1.537 + "Bootstrapped manifest not allowed to use '%s' directive.", 1.538 + token); 1.539 + continue; 1.540 + } 1.541 + 1.542 + if (directive->componentonly && NS_SKIN_LOCATION == type) { 1.543 + LogMessageWithContext(file, line, 1.544 + "Skin manifest not allowed to use '%s' directive.", 1.545 + token); 1.546 + continue; 1.547 + } 1.548 + 1.549 + NS_ASSERTION(directive->argc < 4, "Need to reset argv array length"); 1.550 + char* argv[4]; 1.551 + for (int i = 0; i < directive->argc; ++i) 1.552 + argv[i] = nsCRT::strtok(whitespace, kWhitespace, &whitespace); 1.553 + 1.554 + if (!argv[directive->argc - 1]) { 1.555 + LogMessageWithContext(file, line, 1.556 + "Not enough arguments for chrome manifest directive '%s', expected %i.", 1.557 + token, directive->argc); 1.558 + continue; 1.559 + } 1.560 + 1.561 + bool ok = true; 1.562 + TriState stAppVersion = eUnspecified; 1.563 + TriState stGeckoVersion = eUnspecified; 1.564 + TriState stApp = eUnspecified; 1.565 + TriState stOsVersion = eUnspecified; 1.566 + TriState stOs = eUnspecified; 1.567 + TriState stABI = eUnspecified; 1.568 +#if defined(MOZ_WIDGET_ANDROID) 1.569 + TriState stTablet = eUnspecified; 1.570 +#endif 1.571 + bool platform = false; 1.572 + bool contentAccessible = false; 1.573 + 1.574 + while (nullptr != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && ok) { 1.575 + ToLowerCase(token); 1.576 + NS_ConvertASCIItoUTF16 wtoken(token); 1.577 + 1.578 + if (CheckStringFlag(kApplication, wtoken, appID, stApp) || 1.579 + CheckStringFlag(kOs, wtoken, osTarget, stOs) || 1.580 + CheckStringFlag(kABI, wtoken, abi, stABI) || 1.581 + CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) || 1.582 + CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) || 1.583 + CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, stGeckoVersion)) 1.584 + continue; 1.585 + 1.586 +#if defined(MOZ_WIDGET_ANDROID) 1.587 + bool tablet = false; 1.588 + if (CheckFlag(kTablet, wtoken, tablet)) { 1.589 + stTablet = (tablet == isTablet) ? eOK : eBad; 1.590 + continue; 1.591 + } 1.592 +#endif 1.593 + 1.594 + if (directive->contentflags && 1.595 + (CheckFlag(kPlatform, wtoken, platform) || 1.596 + CheckFlag(kContentAccessible, wtoken, contentAccessible))) 1.597 + continue; 1.598 + 1.599 + bool xpcNativeWrappers = true; // Dummy for CheckFlag. 1.600 + if (CheckFlag(kXPCNativeWrappers, wtoken, xpcNativeWrappers)) { 1.601 + LogMessageWithContext(file, line, 1.602 + "Ignoring obsolete chrome registration modifier '%s'.", 1.603 + token); 1.604 + continue; 1.605 + } 1.606 + 1.607 + LogMessageWithContext(file, line, 1.608 + "Unrecognized chrome manifest modifier '%s'.", 1.609 + token); 1.610 + ok = false; 1.611 + } 1.612 + 1.613 + if (!ok || 1.614 + stApp == eBad || 1.615 + stAppVersion == eBad || 1.616 + stGeckoVersion == eBad || 1.617 + stOs == eBad || 1.618 + stOsVersion == eBad || 1.619 +#ifdef MOZ_WIDGET_ANDROID 1.620 + stTablet == eBad || 1.621 +#endif 1.622 + stABI == eBad) 1.623 + continue; 1.624 + 1.625 + if (directive->regfunc) { 1.626 + if (GeckoProcessType_Default != XRE_GetProcessType()) 1.627 + continue; 1.628 + 1.629 + if (!nsChromeRegistry::gChromeRegistry) { 1.630 + nsCOMPtr<nsIChromeRegistry> cr = 1.631 + mozilla::services::GetChromeRegistryService(); 1.632 + if (!nsChromeRegistry::gChromeRegistry) { 1.633 + LogMessageWithContext(file, line, 1.634 + "Chrome registry isn't available yet."); 1.635 + continue; 1.636 + } 1.637 + } 1.638 + 1.639 + (nsChromeRegistry::gChromeRegistry->*(directive->regfunc)) 1.640 + (chromecx, line, argv, platform, contentAccessible); 1.641 + } 1.642 + else if (directive->ischrome || !aChromeOnly) { 1.643 + if (directive->isContract) { 1.644 + CachedDirective* cd = contracts.AppendElement(); 1.645 + cd->lineno = line; 1.646 + cd->argv[0] = argv[0]; 1.647 + cd->argv[1] = argv[1]; 1.648 + } 1.649 + else 1.650 + (nsComponentManagerImpl::gComponentManager->*(directive->mgrfunc)) 1.651 + (mgrcx, line, argv); 1.652 + } 1.653 + } 1.654 + 1.655 + for (uint32_t i = 0; i < contracts.Length(); ++i) { 1.656 + CachedDirective& d = contracts[i]; 1.657 + nsComponentManagerImpl::gComponentManager->ManifestContract 1.658 + (mgrcx, d.lineno, d.argv); 1.659 + } 1.660 +}