summaryrefslogtreecommitdiff
path: root/onlineupdate/source
diff options
context:
space:
mode:
Diffstat (limited to 'onlineupdate/source')
-rw-r--r--onlineupdate/source/update/common/pathhash.cxx (renamed from onlineupdate/source/update/common/pathhash.cpp)2
-rw-r--r--onlineupdate/source/update/common/readstrings.cxx (renamed from onlineupdate/source/update/common/readstrings.cpp)2
-rw-r--r--onlineupdate/source/update/common/readstrings.h2
-rw-r--r--onlineupdate/source/update/common/uachelper.cxx (renamed from onlineupdate/source/update/common/uachelper.cpp)2
-rw-r--r--onlineupdate/source/update/common/updatedefines.h4
-rw-r--r--onlineupdate/source/update/common/updatehelper.cxx (renamed from onlineupdate/source/update/common/updatehelper.cpp)2
-rw-r--r--onlineupdate/source/update/common/updatelogging.cxx (renamed from onlineupdate/source/update/common/updatelogging.cpp)2
-rw-r--r--onlineupdate/source/update/common/win_dirent.h7
-rw-r--r--onlineupdate/source/update/inc/mozilla/Assertions.h503
-rw-r--r--onlineupdate/source/update/inc/mozilla/Attributes.h481
-rw-r--r--onlineupdate/source/update/inc/mozilla/Compiler.h110
-rw-r--r--onlineupdate/source/update/inc/mozilla/Likely.h23
-rw-r--r--onlineupdate/source/update/inc/mozilla/MacroArgs.h105
-rw-r--r--onlineupdate/source/update/inc/mozilla/TypeTraits.h1116
-rw-r--r--onlineupdate/source/update/inc/mozilla/Types.h134
-rw-r--r--onlineupdate/source/update/inc/mozilla/nsTraceRefcnt.h67
-rw-r--r--onlineupdate/source/update/src/Makefile.in13
-rw-r--r--onlineupdate/source/update/src/mar.h198
-rw-r--r--onlineupdate/source/update/src/mar_cmdline.h110
-rw-r--r--onlineupdate/source/update/src/mar_create.c399
-rw-r--r--onlineupdate/source/update/src/mar_extract.c83
-rw-r--r--onlineupdate/source/update/src/mar_private.h79
-rw-r--r--onlineupdate/source/update/src/mar_read.c570
-rw-r--r--onlineupdate/source/update/src/moz.build30
-rw-r--r--onlineupdate/source/update/updater/archivereader.cxx (renamed from onlineupdate/source/update/updater/archivereader.cpp)12
-rw-r--r--onlineupdate/source/update/updater/archivereader.h2
-rw-r--r--onlineupdate/source/update/updater/automounter_gonk.cxx (renamed from onlineupdate/source/update/updater/automounter_gonk.cpp)0
-rw-r--r--onlineupdate/source/update/updater/bspatch.cxx (renamed from onlineupdate/source/update/updater/bspatch.cpp)4
-rw-r--r--onlineupdate/source/update/updater/loaddlls.cxx (renamed from onlineupdate/source/update/updater/loaddlls.cpp)3
-rw-r--r--onlineupdate/source/update/updater/progressui-unused/progressui_gonk.cxx (renamed from onlineupdate/source/update/updater/progressui_gonk.cpp)0
-rw-r--r--onlineupdate/source/update/updater/progressui-unused/progressui_osx.mm (renamed from onlineupdate/source/update/updater/progressui_osx.mm)0
-rw-r--r--onlineupdate/source/update/updater/progressui.h4
-rw-r--r--onlineupdate/source/update/updater/progressui_gtk.cxx (renamed from onlineupdate/source/update/updater/progressui_gtk.cpp)2
-rw-r--r--onlineupdate/source/update/updater/progressui_null.cxx (renamed from onlineupdate/source/update/updater/progressui_null.cpp)2
-rw-r--r--onlineupdate/source/update/updater/progressui_win.cxx (renamed from onlineupdate/source/update/updater/progressui_win.cpp)2
-rw-r--r--onlineupdate/source/update/updater/updater.cxx (renamed from onlineupdate/source/update/updater/updater.cpp)129
-rw-r--r--onlineupdate/source/update/updater/win_dirent.cxx (renamed from onlineupdate/source/update/updater/win_dirent.cpp)3
-rw-r--r--onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx379
-rw-r--r--onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h173
39 files changed, 4672 insertions, 87 deletions
diff --git a/onlineupdate/source/update/common/pathhash.cpp b/onlineupdate/source/update/common/pathhash.cxx
index 540a8fd20903..fea123cda366 100644
--- a/onlineupdate/source/update/common/pathhash.cpp
+++ b/onlineupdate/source/update/common/pathhash.cxx
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifdef WNT
#include <windows.h>
#include <wincrypt.h>
#include "pathhash.h"
@@ -137,3 +138,4 @@ CalculateRegistryPathFromFilePath(const LPCWSTR filePath,
delete[] hash;
return TRUE;
}
+#endif
diff --git a/onlineupdate/source/update/common/readstrings.cpp b/onlineupdate/source/update/common/readstrings.cxx
index 428c91c0ba69..83580a80bc74 100644
--- a/onlineupdate/source/update/common/readstrings.cpp
+++ b/onlineupdate/source/update/common/readstrings.cxx
@@ -10,7 +10,7 @@
#include "readstrings.h"
#include "errors.h"
-#ifdef XP_WIN
+#ifdef WNT
# define NS_tfopen _wfopen
# define OPEN_MODE L"rb"
#else
diff --git a/onlineupdate/source/update/common/readstrings.h b/onlineupdate/source/update/common/readstrings.h
index ccc26e3fe935..99e515daa611 100644
--- a/onlineupdate/source/update/common/readstrings.h
+++ b/onlineupdate/source/update/common/readstrings.h
@@ -9,7 +9,7 @@
#define MAX_TEXT_LEN 600
-#ifdef XP_WIN
+#ifdef WNT
# include <windows.h>
typedef WCHAR NS_tchar;
#else
diff --git a/onlineupdate/source/update/common/uachelper.cpp b/onlineupdate/source/update/common/uachelper.cxx
index 90ccdb76b4bd..55053f3d7932 100644
--- a/onlineupdate/source/update/common/uachelper.cpp
+++ b/onlineupdate/source/update/common/uachelper.cxx
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifdef WNT
#include <windows.h>
#include <wtsapi32.h>
#include "uachelper.h"
@@ -220,3 +221,4 @@ UACHelper::CanUserElevate()
return canElevate;
}
+#endif
diff --git a/onlineupdate/source/update/common/updatedefines.h b/onlineupdate/source/update/common/updatedefines.h
index 0f62dbe2c50b..db4553312384 100644
--- a/onlineupdate/source/update/common/updatedefines.h
+++ b/onlineupdate/source/update/common/updatedefines.h
@@ -21,7 +21,7 @@
# endif
#endif
-#if defined(XP_WIN)
+#if defined(WNT)
# include <windows.h>
# include <shlwapi.h>
# include <direct.h>
@@ -116,7 +116,7 @@ static inline int mywcsprintf(WCHAR* dest, size_t count, const WCHAR* fmt, ...)
#endif
# include <dirent.h>
-#ifdef XP_MACOSX
+#ifdef MACOSX
# include <sys/time.h>
#endif
diff --git a/onlineupdate/source/update/common/updatehelper.cpp b/onlineupdate/source/update/common/updatehelper.cxx
index 84ab331a6052..579515430115 100644
--- a/onlineupdate/source/update/common/updatehelper.cpp
+++ b/onlineupdate/source/update/common/updatehelper.cxx
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifdef WNT
#include <windows.h>
// Needed for CreateToolhelp32Snapshot
@@ -749,3 +750,4 @@ IsUnpromptedElevation(BOOL &isUnpromptedElevation)
RegCloseKey(baseKey);
return success;
}
+#endif
diff --git a/onlineupdate/source/update/common/updatelogging.cpp b/onlineupdate/source/update/common/updatelogging.cxx
index 036c0b175ae6..9ed8f3e8fcea 100644
--- a/onlineupdate/source/update/common/updatelogging.cpp
+++ b/onlineupdate/source/update/common/updatelogging.cxx
@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#if defined(XP_WIN)
+#if defined(WNT)
#include <windows.h>
#endif
diff --git a/onlineupdate/source/update/common/win_dirent.h b/onlineupdate/source/update/common/win_dirent.h
index 28f5317ff3e1..a1c79d6cdc78 100644
--- a/onlineupdate/source/update/common/win_dirent.h
+++ b/onlineupdate/source/update/common/win_dirent.h
@@ -6,11 +6,7 @@
#ifndef WINDIRENT_H__
#define WINDIRENT_H__
-
-#ifndef XP_WIN
-#error This library should only be used on Windows
-#endif
-
+#ifdef WNT
#include <windows.h>
struct DIR {
@@ -29,4 +25,5 @@ DIR* opendir(const WCHAR* path);
int closedir(DIR* dir);
dirent* readdir(DIR* dir);
+#endif // WNT
#endif // WINDIRENT_H__
diff --git a/onlineupdate/source/update/inc/mozilla/Assertions.h b/onlineupdate/source/update/inc/mozilla/Assertions.h
new file mode 100644
index 000000000000..c72e020806cd
--- /dev/null
+++ b/onlineupdate/source/update/inc/mozilla/Assertions.h
@@ -0,0 +1,503 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implementations of runtime and static assertion macros for C and C++. */
+
+#ifndef mozilla_Assertions_h
+#define mozilla_Assertions_h
+
+#if defined(MOZILLA_INTERNAL_API) && defined(__cplusplus)
+#define MOZ_DUMP_ASSERTION_STACK
+#endif
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Compiler.h"
+#include "mozilla/Likely.h"
+#include "mozilla/MacroArgs.h"
+#ifdef MOZ_DUMP_ASSERTION_STACK
+#include "nsTraceRefcnt.h"
+#endif
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef WIN32
+ /*
+ * TerminateProcess and GetCurrentProcess are defined in <winbase.h>, which
+ * further depends on <windef.h>. We hardcode these few definitions manually
+ * because those headers clutter the global namespace with a significant
+ * number of undesired macros and symbols.
+ */
+# ifdef __cplusplus
+extern "C" {
+# endif
+__declspec(dllimport) int __stdcall
+TerminateProcess(void* hProcess, unsigned int uExitCode);
+__declspec(dllimport) void* __stdcall GetCurrentProcess(void);
+# ifdef __cplusplus
+}
+# endif
+#else
+# include <signal.h>
+#endif
+#ifdef ANDROID
+# include <android/log.h>
+#endif
+
+/*
+ * MOZ_STATIC_ASSERT may be used to assert a condition *at compile time* in C.
+ * In C++11, static_assert is provided by the compiler to the same effect.
+ * This can be useful when you make certain assumptions about what must hold for
+ * optimal, or even correct, behavior. For example, you might assert that the
+ * size of a struct is a multiple of the target architecture's word size:
+ *
+ * struct S { ... };
+ * // C
+ * MOZ_STATIC_ASSERT(sizeof(S) % sizeof(size_t) == 0,
+ * "S should be a multiple of word size for efficiency");
+ * // C++11
+ * static_assert(sizeof(S) % sizeof(size_t) == 0,
+ * "S should be a multiple of word size for efficiency");
+ *
+ * This macro can be used in any location where both an extern declaration and a
+ * typedef could be used.
+ */
+#ifndef __cplusplus
+ /*
+ * Some of the definitions below create an otherwise-unused typedef. This
+ * triggers compiler warnings with some versions of gcc, so mark the typedefs
+ * as permissibly-unused to disable the warnings.
+ */
+# if defined(__GNUC__)
+# define MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
+# else
+# define MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE /* nothing */
+# endif
+# define MOZ_STATIC_ASSERT_GLUE1(x, y) x##y
+# define MOZ_STATIC_ASSERT_GLUE(x, y) MOZ_STATIC_ASSERT_GLUE1(x, y)
+# if defined(__SUNPRO_CC)
+ /*
+ * The Sun Studio C++ compiler is buggy when declaring, inside a function,
+ * another extern'd function with an array argument whose length contains a
+ * sizeof, triggering the error message "sizeof expression not accepted as
+ * size of array parameter". This bug (6688515, not public yet) would hit
+ * defining moz_static_assert as a function, so we always define an extern
+ * array for Sun Studio.
+ *
+ * We include the line number in the symbol name in a best-effort attempt
+ * to avoid conflicts (see below).
+ */
+# define MOZ_STATIC_ASSERT(cond, reason) \
+ extern char MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)[(cond) ? 1 : -1]
+# elif defined(__COUNTER__)
+ /*
+ * If there was no preferred alternative, use a compiler-agnostic version.
+ *
+ * Note that the non-__COUNTER__ version has a bug in C++: it can't be used
+ * in both |extern "C"| and normal C++ in the same translation unit. (Alas
+ * |extern "C"| isn't allowed in a function.) The only affected compiler
+ * we really care about is gcc 4.2. For that compiler and others like it,
+ * we include the line number in the function name to do the best we can to
+ * avoid conflicts. These should be rare: a conflict would require use of
+ * MOZ_STATIC_ASSERT on the same line in separate files in the same
+ * translation unit, *and* the uses would have to be in code with
+ * different linkage, *and* the first observed use must be in C++-linkage
+ * code.
+ */
+# define MOZ_STATIC_ASSERT(cond, reason) \
+ typedef int MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __COUNTER__)[(cond) ? 1 : -1] MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE
+# else
+# define MOZ_STATIC_ASSERT(cond, reason) \
+ extern void MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)(int arg[(cond) ? 1 : -1]) MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE
+# endif
+
+#define MOZ_STATIC_ASSERT_IF(cond, expr, reason) MOZ_STATIC_ASSERT(!(cond) || (expr), reason)
+#else
+#define MOZ_STATIC_ASSERT_IF(cond, expr, reason) static_assert(!(cond) || (expr), reason)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Prints |aStr| as an assertion failure (using aFilename and aLine as the
+ * location of the assertion) to the standard debug-output channel.
+ *
+ * Usually you should use MOZ_ASSERT or MOZ_CRASH instead of this method. This
+ * method is primarily for internal use in this header, and only secondarily
+ * for use in implementing release-build assertions.
+ */
+static MOZ_COLD MOZ_ALWAYS_INLINE void
+MOZ_ReportAssertionFailure(const char* aStr, const char* aFilename, int aLine)
+ MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
+{
+#ifdef ANDROID
+ __android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert",
+ "Assertion failure: %s, at %s:%d\n",
+ aStr, aFilename, aLine);
+#else
+ fprintf(stderr, "Assertion failure: %s, at %s:%d\n", aStr, aFilename, aLine);
+#if defined (MOZ_DUMP_ASSERTION_STACK) && !defined(MOZILLA_XPCOMRT_API)
+ nsTraceRefcnt::WalkTheStack(stderr);
+#endif
+ fflush(stderr);
+#endif
+}
+
+static MOZ_COLD MOZ_ALWAYS_INLINE void
+MOZ_ReportCrash(const char* aStr, const char* aFilename, int aLine)
+ MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
+{
+#ifdef ANDROID
+ __android_log_print(ANDROID_LOG_FATAL, "MOZ_CRASH",
+ "Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine);
+#else
+ fprintf(stderr, "Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine);
+#if defined(MOZ_DUMP_ASSERTION_STACK) && !defined(MOZILLA_XPCOMRT_API)
+ nsTraceRefcnt::WalkTheStack(stderr);
+#endif
+ fflush(stderr);
+#endif
+}
+
+/**
+ * MOZ_REALLY_CRASH is used in the implementation of MOZ_CRASH(). You should
+ * call MOZ_CRASH instead.
+ */
+#if defined(_MSC_VER)
+ /*
+ * On MSVC use the __debugbreak compiler intrinsic, which produces an inline
+ * (not nested in a system function) breakpoint. This distinctively invokes
+ * Breakpad without requiring system library symbols on all stack-processing
+ * machines, as a nested breakpoint would require.
+ *
+ * We use TerminateProcess with the exit code aborting would generate
+ * because we don't want to invoke atexit handlers, destructors, library
+ * unload handlers, and so on when our process might be in a compromised
+ * state.
+ *
+ * We don't use abort() because it'd cause Windows to annoyingly pop up the
+ * process error dialog multiple times. See bug 345118 and bug 426163.
+ *
+ * We follow TerminateProcess() with a call to MOZ_NoReturn() so that the
+ * compiler doesn't hassle us to provide a return statement after a
+ * MOZ_REALLY_CRASH() call.
+ *
+ * (Technically these are Windows requirements, not MSVC requirements. But
+ * practically you need MSVC for debugging, and we only ship builds created
+ * by MSVC, so doing it this way reduces complexity.)
+ */
+
+__declspec(noreturn) __inline void MOZ_NoReturn() {}
+
+# ifdef __cplusplus
+# define MOZ_REALLY_CRASH() \
+ do { \
+ ::__debugbreak(); \
+ *((volatile int*) NULL) = __LINE__; \
+ ::TerminateProcess(::GetCurrentProcess(), 3); \
+ ::MOZ_NoReturn(); \
+ } while (0)
+# else
+# define MOZ_REALLY_CRASH() \
+ do { \
+ __debugbreak(); \
+ *((volatile int*) NULL) = __LINE__; \
+ TerminateProcess(GetCurrentProcess(), 3); \
+ MOZ_NoReturn(); \
+ } while (0)
+# endif
+#else
+# ifdef __cplusplus
+# define MOZ_REALLY_CRASH() \
+ do { \
+ *((volatile int*) NULL) = __LINE__; \
+ ::abort(); \
+ } while (0)
+# else
+# define MOZ_REALLY_CRASH() \
+ do { \
+ *((volatile int*) NULL) = __LINE__; \
+ abort(); \
+ } while (0)
+# endif
+#endif
+
+/*
+ * MOZ_CRASH([explanation-string]) crashes the program, plain and simple, in a
+ * Breakpad-compatible way, in both debug and release builds.
+ *
+ * MOZ_CRASH is a good solution for "handling" failure cases when you're
+ * unwilling or unable to handle them more cleanly -- for OOM, for likely memory
+ * corruption, and so on. It's also a good solution if you need safe behavior
+ * in release builds as well as debug builds. But if the failure is one that
+ * should be debugged and fixed, MOZ_ASSERT is generally preferable.
+ *
+ * The optional explanation-string, if provided, must be a string literal
+ * explaining why we're crashing. This argument is intended for use with
+ * MOZ_CRASH() calls whose rationale is non-obvious; don't use it if it's
+ * obvious why we're crashing.
+ *
+ * If we're a DEBUG build and we crash at a MOZ_CRASH which provides an
+ * explanation-string, we print the string to stderr. Otherwise, we don't
+ * print anything; this is because we want MOZ_CRASH to be 100% safe in release
+ * builds, and it's hard to print to stderr safely when memory might have been
+ * corrupted.
+ */
+#ifndef DEBUG
+# define MOZ_CRASH(...) MOZ_REALLY_CRASH()
+#else
+# define MOZ_CRASH(...) \
+ do { \
+ MOZ_ReportCrash("" __VA_ARGS__, __FILE__, __LINE__); \
+ MOZ_REALLY_CRASH(); \
+ } while (0)
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+/*
+ * MOZ_ASSERT(expr [, explanation-string]) asserts that |expr| must be truthy in
+ * debug builds. If it is, execution continues. Otherwise, an error message
+ * including the expression and the explanation-string (if provided) is printed,
+ * an attempt is made to invoke any existing debugger, and execution halts.
+ * MOZ_ASSERT is fatal: no recovery is possible. Do not assert a condition
+ * which can correctly be falsy.
+ *
+ * The optional explanation-string, if provided, must be a string literal
+ * explaining the assertion. It is intended for use with assertions whose
+ * correctness or rationale is non-obvious, and for assertions where the "real"
+ * condition being tested is best described prosaically. Don't provide an
+ * explanation if it's not actually helpful.
+ *
+ * // No explanation needed: pointer arguments often must not be NULL.
+ * MOZ_ASSERT(arg);
+ *
+ * // An explanation can be helpful to explain exactly how we know an
+ * // assertion is valid.
+ * MOZ_ASSERT(state == WAITING_FOR_RESPONSE,
+ * "given that <thingA> and <thingB>, we must have...");
+ *
+ * // Or it might disambiguate multiple identical (save for their location)
+ * // assertions of the same expression.
+ * MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(),
+ * "we already set [[PrimitiveThis]] for this Boolean object");
+ * MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(),
+ * "we already set [[PrimitiveThis]] for this String object");
+ *
+ * MOZ_ASSERT has no effect in non-debug builds. It is designed to catch bugs
+ * *only* during debugging, not "in the field". If you want the latter, use
+ * MOZ_RELEASE_ASSERT, which applies to non-debug builds as well.
+ *
+ * MOZ_DIAGNOSTIC_ASSERT works like MOZ_RELEASE_ASSERT in Nightly/Aurora and
+ * MOZ_ASSERT in Beta/Release - use this when a condition is potentially rare
+ * enough to require real user testing to hit, but is not security-sensitive.
+ * This can cause user pain, so use it sparingly. If a MOZ_DIAGNOSTIC_ASSERT
+ * is firing, it should promptly be converted to a MOZ_ASSERT while the failure
+ * is being investigated, rather than letting users suffer.
+ */
+
+/*
+ * Implement MOZ_VALIDATE_ASSERT_CONDITION_TYPE, which is used to guard against
+ * accidentally passing something unintended in lieu of an assertion condition.
+ */
+
+#ifdef __cplusplus
+# include "mozilla/TypeTraits.h"
+namespace mozilla {
+namespace detail {
+
+template<typename T>
+struct IsFunction
+{
+ static const bool value = false;
+};
+
+template<typename R, typename... A>
+struct IsFunction<R(A...)>
+{
+ static const bool value = true;
+};
+
+template<typename T>
+struct AssertionConditionType
+{
+ typedef typename RemoveReference<T>::Type ValueT;
+ static_assert(!IsArray<ValueT>::value,
+ "Expected boolean assertion condition, got an array or a "
+ "string!");
+ static_assert(!IsFunction<ValueT>::value,
+ "Expected boolean assertion condition, got a function! Did "
+ "you intend to call that function?");
+ static_assert(!IsFloatingPoint<ValueT>::value,
+ "It's often a bad idea to assert that a floating-point number "
+ "is nonzero, because such assertions tend to intermittently "
+ "fail. Shouldn't your code gracefully handle this case instead "
+ "of asserting? Anyway, if you really want to do that, write an "
+ "explicit boolean condition, like !!x or x!=0.");
+
+ static const bool isValid = true;
+};
+
+} // namespace detail
+} // namespace mozilla
+# define MOZ_VALIDATE_ASSERT_CONDITION_TYPE(x) \
+ static_assert(mozilla::detail::AssertionConditionType<decltype(x)>::isValid, \
+ "invalid assertion condition")
+#else
+# define MOZ_VALIDATE_ASSERT_CONDITION_TYPE(x)
+#endif
+
+/* First the single-argument form. */
+#define MOZ_ASSERT_HELPER1(expr) \
+ do { \
+ MOZ_VALIDATE_ASSERT_CONDITION_TYPE(expr); \
+ if (MOZ_UNLIKELY(!(expr))) { \
+ MOZ_ReportAssertionFailure(#expr, __FILE__, __LINE__); \
+ MOZ_REALLY_CRASH(); \
+ } \
+ } while (0)
+/* Now the two-argument form. */
+#define MOZ_ASSERT_HELPER2(expr, explain) \
+ do { \
+ MOZ_VALIDATE_ASSERT_CONDITION_TYPE(expr); \
+ if (MOZ_UNLIKELY(!(expr))) { \
+ MOZ_ReportAssertionFailure(#expr " (" explain ")", __FILE__, __LINE__); \
+ MOZ_REALLY_CRASH(); \
+ } \
+ } while (0)
+
+#define MOZ_RELEASE_ASSERT_GLUE(a, b) a b
+#define MOZ_RELEASE_ASSERT(...) \
+ MOZ_RELEASE_ASSERT_GLUE( \
+ MOZ_PASTE_PREFIX_AND_ARG_COUNT(MOZ_ASSERT_HELPER, __VA_ARGS__), \
+ (__VA_ARGS__))
+
+#ifdef DEBUG
+# define MOZ_ASSERT(...) MOZ_RELEASE_ASSERT(__VA_ARGS__)
+#else
+# define MOZ_ASSERT(...) do { } while (0)
+#endif /* DEBUG */
+
+#ifdef RELEASE_BUILD
+# define MOZ_DIAGNOSTIC_ASSERT MOZ_ASSERT
+#else
+# define MOZ_DIAGNOSTIC_ASSERT MOZ_RELEASE_ASSERT
+#endif
+
+/*
+ * MOZ_ASSERT_IF(cond1, cond2) is equivalent to MOZ_ASSERT(cond2) if cond1 is
+ * true.
+ *
+ * MOZ_ASSERT_IF(isPrime(num), num == 2 || isOdd(num));
+ *
+ * As with MOZ_ASSERT, MOZ_ASSERT_IF has effect only in debug builds. It is
+ * designed to catch bugs during debugging, not "in the field".
+ */
+#ifdef DEBUG
+# define MOZ_ASSERT_IF(cond, expr) \
+ do { \
+ if (cond) { \
+ MOZ_ASSERT(expr); \
+ } \
+ } while (0)
+#else
+# define MOZ_ASSERT_IF(cond, expr) do { } while (0)
+#endif
+
+/*
+ * MOZ_ASSUME_UNREACHABLE_MARKER() expands to an expression which states that
+ * it is undefined behavior for execution to reach this point. No guarantees
+ * are made about what will happen if this is reached at runtime. Most code
+ * should use MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE because it has extra
+ * asserts.
+ */
+#if defined(__clang__) || defined(__GNUC__)
+# define MOZ_ASSUME_UNREACHABLE_MARKER() __builtin_unreachable()
+#elif defined(_MSC_VER)
+# define MOZ_ASSUME_UNREACHABLE_MARKER() __assume(0)
+#else
+# ifdef __cplusplus
+# define MOZ_ASSUME_UNREACHABLE_MARKER() ::abort()
+# else
+# define MOZ_ASSUME_UNREACHABLE_MARKER() abort()
+# endif
+#endif
+
+/*
+ * MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE([reason]) tells the compiler that it
+ * can assume that the macro call cannot be reached during execution. This lets
+ * the compiler generate better-optimized code under some circumstances, at the
+ * expense of the program's behavior being undefined if control reaches the
+ * MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE.
+ *
+ * In Gecko, you probably should not use this macro outside of performance- or
+ * size-critical code, because it's unsafe. If you don't care about code size
+ * or performance, you should probably use MOZ_ASSERT or MOZ_CRASH.
+ *
+ * SpiderMonkey is a different beast, and there it's acceptable to use
+ * MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE more widely.
+ *
+ * Note that MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE is noreturn, so it's valid
+ * not to return a value following a MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE
+ * call.
+ *
+ * Example usage:
+ *
+ * enum ValueType {
+ * VALUE_STRING,
+ * VALUE_INT,
+ * VALUE_FLOAT
+ * };
+ *
+ * int ptrToInt(ValueType type, void* value) {
+ * {
+ * // We know for sure that type is either INT or FLOAT, and we want this
+ * // code to run as quickly as possible.
+ * switch (type) {
+ * case VALUE_INT:
+ * return *(int*) value;
+ * case VALUE_FLOAT:
+ * return (int) *(float*) value;
+ * default:
+ * MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unexpected ValueType");
+ * }
+ * }
+ */
+
+/*
+ * Unconditional assert in debug builds for (assumed) unreachable code paths
+ * that have a safe return without crashing in release builds.
+ */
+#define MOZ_ASSERT_UNREACHABLE(reason) \
+ MOZ_ASSERT(false, "MOZ_ASSERT_UNREACHABLE: " reason)
+
+#define MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(reason) \
+ do { \
+ MOZ_ASSERT_UNREACHABLE(reason); \
+ MOZ_ASSUME_UNREACHABLE_MARKER(); \
+ } while (0)
+
+/*
+ * MOZ_ALWAYS_TRUE(expr) and MOZ_ALWAYS_FALSE(expr) always evaluate the provided
+ * expression, in debug builds and in release builds both. Then, in debug
+ * builds only, the value of the expression is asserted either true or false
+ * using MOZ_ASSERT.
+ */
+#ifdef DEBUG
+# define MOZ_ALWAYS_TRUE(expr) MOZ_ASSERT((expr))
+# define MOZ_ALWAYS_FALSE(expr) MOZ_ASSERT(!(expr))
+#else
+# define MOZ_ALWAYS_TRUE(expr) ((void)(expr))
+# define MOZ_ALWAYS_FALSE(expr) ((void)(expr))
+#endif
+
+#undef MOZ_DUMP_ASSERTION_STACK
+
+#endif /* mozilla_Assertions_h */
diff --git a/onlineupdate/source/update/inc/mozilla/Attributes.h b/onlineupdate/source/update/inc/mozilla/Attributes.h
new file mode 100644
index 000000000000..b34e7d5af07a
--- /dev/null
+++ b/onlineupdate/source/update/inc/mozilla/Attributes.h
@@ -0,0 +1,481 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implementations of various class and method modifier attributes. */
+
+#ifndef mozilla_Attributes_h
+#define mozilla_Attributes_h
+
+#include "mozilla/Compiler.h"
+
+/*
+ * MOZ_ALWAYS_INLINE is a macro which expands to tell the compiler that the
+ * method decorated with it must be inlined, even if the compiler thinks
+ * otherwise. This is only a (much) stronger version of the inline hint:
+ * compilers are not guaranteed to respect it (although they're much more likely
+ * to do so).
+ *
+ * The MOZ_ALWAYS_INLINE_EVEN_DEBUG macro is yet stronger. It tells the
+ * compiler to inline even in DEBUG builds. It should be used very rarely.
+ */
+#if defined(_MSC_VER)
+# define MOZ_ALWAYS_INLINE_EVEN_DEBUG __forceinline
+#elif defined(__GNUC__)
+# define MOZ_ALWAYS_INLINE_EVEN_DEBUG __attribute__((always_inline)) inline
+#else
+# define MOZ_ALWAYS_INLINE_EVEN_DEBUG inline
+#endif
+
+#if !defined(DEBUG)
+# define MOZ_ALWAYS_INLINE MOZ_ALWAYS_INLINE_EVEN_DEBUG
+#elif defined(_MSC_VER) && !defined(__cplusplus)
+# define MOZ_ALWAYS_INLINE __inline
+#else
+# define MOZ_ALWAYS_INLINE inline
+#endif
+
+#if defined(_MSC_VER)
+/*
+ * g++ requires -std=c++0x or -std=gnu++0x to support C++11 functionality
+ * without warnings (functionality used by the macros below). These modes are
+ * detectable by checking whether __GXX_EXPERIMENTAL_CXX0X__ is defined or, more
+ * standardly, by checking whether __cplusplus has a C++11 or greater value.
+ * Current versions of g++ do not correctly set __cplusplus, so we check both
+ * for forward compatibility.
+ *
+ * Even though some versions of MSVC support explicit conversion operators, we
+ * don't indicate support for them here, due to
+ * http://stackoverflow.com/questions/20498142/visual-studio-2013-explicit-keyword-bug
+ */
+# define MOZ_HAVE_NEVER_INLINE __declspec(noinline)
+# define MOZ_HAVE_NORETURN __declspec(noreturn)
+# ifdef __clang__
+ /* clang-cl probably supports constexpr and explicit conversions. */
+# if __has_extension(cxx_constexpr)
+# define MOZ_HAVE_CXX11_CONSTEXPR
+# endif
+# if __has_extension(cxx_explicit_conversions)
+# define MOZ_HAVE_EXPLICIT_CONVERSION
+# endif
+# endif
+#elif defined(__clang__)
+ /*
+ * Per Clang documentation, "Note that marketing version numbers should not
+ * be used to check for language features, as different vendors use different
+ * numbering schemes. Instead, use the feature checking macros."
+ */
+# ifndef __has_extension
+# define __has_extension __has_feature /* compatibility, for older versions of clang */
+# endif
+# if __has_extension(cxx_constexpr)
+# define MOZ_HAVE_CXX11_CONSTEXPR
+# endif
+# if __has_extension(cxx_explicit_conversions)
+# define MOZ_HAVE_EXPLICIT_CONVERSION
+# endif
+# if __has_attribute(noinline)
+# define MOZ_HAVE_NEVER_INLINE __attribute__((noinline))
+# endif
+# if __has_attribute(noreturn)
+# define MOZ_HAVE_NORETURN __attribute__((noreturn))
+# endif
+#elif defined(__GNUC__)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
+# define MOZ_HAVE_CXX11_CONSTEXPR
+# if MOZ_GCC_VERSION_AT_LEAST(4, 8, 0)
+# define MOZ_HAVE_CXX11_CONSTEXPR_IN_TEMPLATES
+# endif
+# define MOZ_HAVE_EXPLICIT_CONVERSION
+# endif
+# define MOZ_HAVE_NEVER_INLINE __attribute__((noinline))
+# define MOZ_HAVE_NORETURN __attribute__((noreturn))
+#endif
+
+/*
+ * When built with clang analyzer (a.k.a scan-build), define MOZ_HAVE_NORETURN
+ * to mark some false positives
+ */
+#ifdef __clang_analyzer__
+# if __has_extension(attribute_analyzer_noreturn)
+# define MOZ_HAVE_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
+# endif
+#endif
+
+/*
+ * The MOZ_CONSTEXPR specifier declares that a C++11 compiler can evaluate a
+ * function at compile time. A constexpr function cannot examine any values
+ * except its arguments and can have no side effects except its return value.
+ * The MOZ_CONSTEXPR_VAR specifier tells a C++11 compiler that a variable's
+ * value may be computed at compile time. It should be prefered to just
+ * marking variables as MOZ_CONSTEXPR because if the compiler does not support
+ * constexpr it will fall back to making the variable const, and some compilers
+ * do not accept variables being marked both const and constexpr.
+ */
+#ifdef MOZ_HAVE_CXX11_CONSTEXPR
+# define MOZ_CONSTEXPR constexpr
+# define MOZ_CONSTEXPR_VAR constexpr
+# ifdef MOZ_HAVE_CXX11_CONSTEXPR_IN_TEMPLATES
+# define MOZ_CONSTEXPR_TMPL constexpr
+# else
+# define MOZ_CONSTEXPR_TMPL
+# endif
+#else
+# define MOZ_CONSTEXPR /* no support */
+# define MOZ_CONSTEXPR_VAR const
+# define MOZ_CONSTEXPR_TMPL
+#endif
+
+/*
+ * MOZ_EXPLICIT_CONVERSION is a specifier on a type conversion
+ * overloaded operator that declares that a C++11 compiler should restrict
+ * this operator to allow only explicit type conversions, disallowing
+ * implicit conversions.
+ *
+ * Example:
+ *
+ * template<typename T>
+ * class Ptr
+ * {
+ * T* mPtr;
+ * MOZ_EXPLICIT_CONVERSION operator bool() const
+ * {
+ * return mPtr != nullptr;
+ * }
+ * };
+ *
+ */
+#ifdef MOZ_HAVE_EXPLICIT_CONVERSION
+# define MOZ_EXPLICIT_CONVERSION explicit
+#else
+# define MOZ_EXPLICIT_CONVERSION /* no support */
+#endif
+
+/*
+ * MOZ_NEVER_INLINE is a macro which expands to tell the compiler that the
+ * method decorated with it must never be inlined, even if the compiler would
+ * otherwise choose to inline the method. Compilers aren't absolutely
+ * guaranteed to support this, but most do.
+ */
+#if defined(MOZ_HAVE_NEVER_INLINE)
+# define MOZ_NEVER_INLINE MOZ_HAVE_NEVER_INLINE
+#else
+# define MOZ_NEVER_INLINE /* no support */
+#endif
+
+/*
+ * MOZ_NORETURN, specified at the start of a function declaration, indicates
+ * that the given function does not return. (The function definition does not
+ * need to be annotated.)
+ *
+ * MOZ_NORETURN void abort(const char* msg);
+ *
+ * This modifier permits the compiler to optimize code assuming a call to such a
+ * function will never return. It also enables the compiler to avoid spurious
+ * warnings about not initializing variables, or about any other seemingly-dodgy
+ * operations performed after the function returns.
+ *
+ * This modifier does not affect the corresponding function's linking behavior.
+ */
+#if defined(MOZ_HAVE_NORETURN)
+# define MOZ_NORETURN MOZ_HAVE_NORETURN
+#else
+# define MOZ_NORETURN /* no support */
+#endif
+
+/**
+ * MOZ_COLD tells the compiler that a function is "cold", meaning infrequently
+ * executed. This may lead it to optimize for size more aggressively than speed,
+ * or to allocate the body of the function in a distant part of the text segment
+ * to help keep it from taking up unnecessary icache when it isn't in use.
+ *
+ * Place this attribute at the very beginning of a function definition. For
+ * example, write
+ *
+ * MOZ_COLD int foo();
+ *
+ * or
+ *
+ * MOZ_COLD int foo() { return 42; }
+ */
+#if defined(__GNUC__) || defined(__clang__)
+# define MOZ_COLD __attribute__ ((cold))
+#else
+# define MOZ_COLD
+#endif
+
+/**
+ * MOZ_NONNULL tells the compiler that some of the arguments to a function are
+ * known to be non-null. The arguments are a list of 1-based argument indexes
+ * identifying arguments which are known to be non-null.
+ *
+ * Place this attribute at the very beginning of a function definition. For
+ * example, write
+ *
+ * MOZ_NONNULL(1, 2) int foo(char *p, char *q);
+ */
+#if defined(__GNUC__) || defined(__clang__)
+# define MOZ_NONNULL(...) __attribute__ ((nonnull(__VA_ARGS__)))
+#else
+# define MOZ_NONNULL(...)
+#endif
+
+/*
+ * MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS, specified at the end of a function
+ * declaration, indicates that for the purposes of static analysis, this
+ * function does not return. (The function definition does not need to be
+ * annotated.)
+ *
+ * MOZ_ReportCrash(const char* s, const char* file, int ln)
+ * MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
+ *
+ * Some static analyzers, like scan-build from clang, can use this information
+ * to eliminate false positives. From the upstream documentation of scan-build:
+ * "This attribute is useful for annotating assertion handlers that actually
+ * can return, but for the purpose of using the analyzer we want to pretend
+ * that such functions do not return."
+ *
+ */
+#if defined(MOZ_HAVE_ANALYZER_NORETURN)
+# define MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS MOZ_HAVE_ANALYZER_NORETURN
+#else
+# define MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS /* no support */
+#endif
+
+/*
+ * MOZ_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time
+ * instrumentation shipped with Clang and GCC) to not instrument the annotated
+ * function. Furthermore, it will prevent the compiler from inlining the
+ * function because inlining currently breaks the blacklisting mechanism of
+ * AddressSanitizer.
+ */
+#if defined(__has_feature)
+# if __has_feature(address_sanitizer)
+# define MOZ_HAVE_ASAN_BLACKLIST
+# endif
+#elif defined(__GNUC__)
+# if defined(__SANITIZE_ADDRESS__)
+# define MOZ_HAVE_ASAN_BLACKLIST
+# endif
+#endif
+
+#if defined(MOZ_HAVE_ASAN_BLACKLIST)
+# define MOZ_ASAN_BLACKLIST MOZ_NEVER_INLINE __attribute__((no_sanitize_address))
+#else
+# define MOZ_ASAN_BLACKLIST /* nothing */
+#endif
+
+/*
+ * MOZ_TSAN_BLACKLIST is a macro to tell ThreadSanitizer (a compile-time
+ * instrumentation shipped with Clang) to not instrument the annotated function.
+ * Furthermore, it will prevent the compiler from inlining the function because
+ * inlining currently breaks the blacklisting mechanism of ThreadSanitizer.
+ */
+#if defined(__has_feature)
+# if __has_feature(thread_sanitizer)
+# define MOZ_TSAN_BLACKLIST MOZ_NEVER_INLINE __attribute__((no_sanitize_thread))
+# else
+# define MOZ_TSAN_BLACKLIST /* nothing */
+# endif
+#else
+# define MOZ_TSAN_BLACKLIST /* nothing */
+#endif
+
+/**
+ * MOZ_ALLOCATOR tells the compiler that the function it marks returns either a
+ * "fresh", "pointer-free" block of memory, or nullptr. "Fresh" means that the
+ * block is not pointed to by any other reachable pointer in the program.
+ * "Pointer-free" means that the block contains no pointers to any valid object
+ * in the program. It may be initialized with other (non-pointer) values.
+ *
+ * Placing this attribute on appropriate functions helps GCC analyze pointer
+ * aliasing more accurately in their callers.
+ *
+ * GCC warns if a caller ignores the value returned by a function marked with
+ * MOZ_ALLOCATOR: it is hard to imagine cases where dropping the value returned
+ * by a function that meets the criteria above would be intentional.
+ *
+ * Place this attribute after the argument list and 'this' qualifiers of a
+ * function definition. For example, write
+ *
+ * void *my_allocator(size_t) MOZ_ALLOCATOR;
+ *
+ * or
+ *
+ * void *my_allocator(size_t bytes) MOZ_ALLOCATOR { ... }
+ */
+#if defined(__GNUC__) || defined(__clang__)
+# define MOZ_ALLOCATOR __attribute__ ((malloc, warn_unused_result))
+#else
+# define MOZ_ALLOCATOR
+#endif
+
+/**
+ * MOZ_WARN_UNUSED_RESULT tells the compiler to emit a warning if a function's
+ * return value is not used by the caller.
+ *
+ * Place this attribute at the very beginning of a function definition. For
+ * example, write
+ *
+ * MOZ_WARN_UNUSED_RESULT int foo();
+ *
+ * or
+ *
+ * MOZ_WARN_UNUSED_RESULT int foo() { return 42; }
+ */
+#if defined(__GNUC__) || defined(__clang__)
+# define MOZ_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
+#else
+# define MOZ_WARN_UNUSED_RESULT
+#endif
+
+#ifdef __cplusplus
+
+/*
+ * The following macros are attributes that support the static analysis plugin
+ * included with Mozilla, and will be implemented (when such support is enabled)
+ * as C++11 attributes. Since such attributes are legal pretty much everywhere
+ * and have subtly different semantics depending on their placement, the
+ * following is a guide on where to place the attributes.
+ *
+ * Attributes that apply to a struct or class precede the name of the class:
+ * (Note that this is different from the placement of final for classes!)
+ *
+ * class MOZ_CLASS_ATTRIBUTE SomeClass {};
+ *
+ * Attributes that apply to functions follow the parentheses and const
+ * qualifiers but precede final, override and the function body:
+ *
+ * void DeclaredFunction() MOZ_FUNCTION_ATTRIBUTE;
+ * void SomeFunction() MOZ_FUNCTION_ATTRIBUTE {}
+ * void PureFunction() const MOZ_FUNCTION_ATTRIBUTE = 0;
+ * void OverriddenFunction() MOZ_FUNCTION_ATTIRBUTE override;
+ *
+ * Attributes that apply to variables or parameters follow the variable's name:
+ *
+ * int variable MOZ_VARIABLE_ATTRIBUTE;
+ *
+ * Attributes that apply to types follow the type name:
+ *
+ * typedef int MOZ_TYPE_ATTRIBUTE MagicInt;
+ * int MOZ_TYPE_ATTRIBUTE someVariable;
+ * int* MOZ_TYPE_ATTRIBUTE magicPtrInt;
+ * int MOZ_TYPE_ATTRIBUTE* ptrToMagicInt;
+ *
+ * Attributes that apply to statements precede the statement:
+ *
+ * MOZ_IF_ATTRIBUTE if (x == 0)
+ * MOZ_DO_ATTRIBUTE do { } while (0);
+ *
+ * Attributes that apply to labels precede the label:
+ *
+ * MOZ_LABEL_ATTRIBUTE target:
+ * goto target;
+ * MOZ_CASE_ATTRIBUTE case 5:
+ * MOZ_DEFAULT_ATTRIBUTE default:
+ *
+ * The static analyses that are performed by the plugin are as follows:
+ *
+ * MOZ_MUST_OVERRIDE: Applies to all C++ member functions. All immediate
+ * subclasses must provide an exact override of this method; if a subclass
+ * does not override this method, the compiler will emit an error. This
+ * attribute is not limited to virtual methods, so if it is applied to a
+ * nonvirtual method and the subclass does not provide an equivalent
+ * definition, the compiler will emit an error.
+ * MOZ_STACK_CLASS: Applies to all classes. Any class with this annotation is
+ * expected to live on the stack, so it is a compile-time error to use it, or
+ * an array of such objects, as a global or static variable, or as the type of
+ * a new expression (unless placement new is being used). If a member of
+ * another class uses this class, or if another class inherits from this
+ * class, then it is considered to be a stack class as well, although this
+ * attribute need not be provided in such cases.
+ * MOZ_NONHEAP_CLASS: Applies to all classes. Any class with this annotation is
+ * expected to live on the stack or in static storage, so it is a compile-time
+ * error to use it, or an array of such objects, as the type of a new
+ * expression (unless placement new is being used). If a member of another
+ * class uses this class, or if another class inherits from this class, then
+ * it is considered to be a non-heap class as well, although this attribute
+ * need not be provided in such cases.
+ * MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS: Applies to all classes that are
+ * intended to prevent introducing static initializers. This attribute
+ * currently makes it a compile-time error to instantiate these classes
+ * anywhere other than at the global scope, or as a static member of a class.
+ * MOZ_TRIVIAL_CTOR_DTOR: Applies to all classes that must have both a trivial
+ * constructor and a trivial destructor. Setting this attribute on a class
+ * makes it a compile-time error for that class to get a non-trivial
+ * constructor or destructor for any reason.
+ * MOZ_HEAP_ALLOCATOR: Applies to any function. This indicates that the return
+ * value is allocated on the heap, and will as a result check such allocations
+ * during MOZ_STACK_CLASS and MOZ_NONHEAP_CLASS annotation checking.
+ * MOZ_IMPLICIT: Applies to constructors. Implicit conversion constructors
+ * are disallowed by default unless they are marked as MOZ_IMPLICIT. This
+ * attribute must be used for constructors which intend to provide implicit
+ * conversions.
+ * MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT: Applies to functions. Makes it a compile
+ * time error to pass arithmetic expressions on variables to the function.
+ * MOZ_OWNING_REF: Applies to declarations of pointer types. This attribute
+ * tells the compiler that the raw pointer is a strong reference, and that
+ * property is somehow enforced by the code. This can make the compiler
+ * ignore these pointers when validating the usage of pointers otherwise.
+ * MOZ_NON_OWNING_REF: Applies to declarations of pointer types. This attribute
+ * tells the compiler that the raw pointer is a weak reference, and that
+ * property is somehow enforced by the code. This can make the compiler
+ * ignore these pointers when validating the usage of pointers otherwise.
+ * MOZ_UNSAFE_REF: Applies to declarations of pointer types. This attribute
+ * should be used for non-owning references that can be unsafe, and their
+ * safety needs to be validated through code inspection. The string argument
+ * passed to this macro documents the safety conditions.
+ * MOZ_NO_ADDREF_RELEASE_ON_RETURN: Applies to function declarations. Makes it
+ * a compile time error to call AddRef or Release on the return value of a
+ * function. This is intended to be used with operator->() of our smart
+ * pointer classes to ensure that the refcount of an object wrapped in a
+ * smart pointer is not manipulated directly.
+ */
+#ifdef MOZ_CLANG_PLUGIN
+# define MOZ_MUST_OVERRIDE __attribute__((annotate("moz_must_override")))
+# define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
+# define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class")))
+# define MOZ_TRIVIAL_CTOR_DTOR __attribute__((annotate("moz_trivial_ctor_dtor")))
+# ifdef DEBUG
+ /* in debug builds, these classes do have non-trivial constructors. */
+# define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS __attribute__((annotate("moz_global_class")))
+# else
+# define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS __attribute__((annotate("moz_global_class"))) \
+ MOZ_TRIVIAL_CTOR_DTOR
+# endif
+# define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
+# define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT __attribute__((annotate("moz_no_arith_expr_in_arg")))
+# define MOZ_OWNING_REF __attribute__((annotate("moz_strong_ref")))
+# define MOZ_NON_OWNING_REF __attribute__((annotate("moz_weak_ref")))
+# define MOZ_UNSAFE_REF(reason) __attribute__((annotate("moz_strong_ref")))
+# define MOZ_NO_ADDREF_RELEASE_ON_RETURN __attribute__((annotate("moz_no_addref_release_on_return")))
+/*
+ * It turns out that clang doesn't like void func() __attribute__ {} without a
+ * warning, so use pragmas to disable the warning. This code won't work on GCC
+ * anyways, so the warning is safe to ignore.
+ */
+# define MOZ_HEAP_ALLOCATOR \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
+ __attribute__((annotate("moz_heap_allocator"))) \
+ _Pragma("clang diagnostic pop")
+#else
+# define MOZ_MUST_OVERRIDE /* nothing */
+# define MOZ_STACK_CLASS /* nothing */
+# define MOZ_NONHEAP_CLASS /* nothing */
+# define MOZ_TRIVIAL_CTOR_DTOR /* nothing */
+# define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS /* nothing */
+# define MOZ_IMPLICIT /* nothing */
+# define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT /* nothing */
+# define MOZ_HEAP_ALLOCATOR /* nothing */
+# define MOZ_OWNING_REF /* nothing */
+# define MOZ_NON_OWNING_REF /* nothing */
+# define MOZ_UNSAFE_REF(reason) /* nothing */
+# define MOZ_NO_ADDREF_RELEASE_ON_RETURN /* nothing */
+#endif /* MOZ_CLANG_PLUGIN */
+
+#endif /* __cplusplus */
+
+#endif /* mozilla_Attributes_h */
diff --git a/onlineupdate/source/update/inc/mozilla/Compiler.h b/onlineupdate/source/update/inc/mozilla/Compiler.h
new file mode 100644
index 000000000000..6d6fcbbb19f5
--- /dev/null
+++ b/onlineupdate/source/update/inc/mozilla/Compiler.h
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Various compiler checks. */
+
+#ifndef mozilla_Compiler_h
+#define mozilla_Compiler_h
+
+#define MOZ_IS_GCC 0
+#define MOS_IS_MSVC 0
+
+#if !defined(__clang__) && defined(__GNUC__)
+
+# undef MOZ_IS_GCC
+# define MOZ_IS_GCC 1
+ /*
+ * This macro should simplify gcc version checking. For example, to check
+ * for gcc 4.7.1 or later, check `#if MOZ_GCC_VERSION_AT_LEAST(4, 7, 1)`.
+ */
+# define MOZ_GCC_VERSION_AT_LEAST(major, minor, patchlevel) \
+ ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \
+ >= ((major) * 10000 + (minor) * 100 + (patchlevel)))
+# if !MOZ_GCC_VERSION_AT_LEAST(4, 7, 0)
+# error "mfbt (and Gecko) require at least gcc 4.7 to build."
+# endif
+
+#elif defined(_MSC_VER)
+
+# undef MOZ_IS_MSVC
+# define MOZ_IS_MSVC 1
+
+#endif
+
+/*
+ * The situation with standard libraries is a lot worse than with compilers,
+ * particularly as clang and gcc could end up using one of three or so standard
+ * libraries, and they may not be up-to-snuff with newer C++11 versions. To
+ * detect the library, we're going to include cstddef (which is a small header
+ * which will be transitively included by everybody else at some point) to grab
+ * the version macros and deduce macros from there.
+ */
+#ifdef __cplusplus
+# include <cstddef>
+# ifdef _STLPORT_MAJOR
+# define MOZ_USING_STLPORT 1
+# define MOZ_STLPORT_VERSION_AT_LEAST(major, minor, patch) \
+ (_STLPORT_VERSION >= ((major) << 8 | (minor) << 4 | (patch)))
+# elif defined(_LIBCPP_VERSION)
+ /*
+ * libc++, unfortunately, doesn't appear to have useful versioning macros.
+ * Hopefully, the recommendations of N3694 with respect to standard libraries
+ * will get applied instead and we won't need to worry about version numbers
+ * here.
+ */
+# define MOZ_USING_LIBCXX 1
+# elif defined(__GLIBCXX__)
+# define MOZ_USING_LIBSTDCXX 1
+ /*
+ * libstdc++ is also annoying and doesn't give us useful versioning macros
+ * for the library. If we're using gcc, then assume that libstdc++ matches
+ * the compiler version. If we're using clang, we're going to have to fake
+ * major/minor combinations by looking for newly-defined config macros.
+ */
+# if MOZ_IS_GCC
+# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+ MOZ_GCC_VERSION_AT_LEAST(major, minor, patch)
+# elif defined(_GLIBCXX_THROW_OR_ABORT)
+# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+ ((major) < 4 || ((major) == 4 && (minor) <= 8))
+# elif defined(_GLIBCXX_NOEXCEPT)
+# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+ ((major) < 4 || ((major) == 4 && (minor) <= 7))
+# elif defined(_GLIBCXX_USE_DEPRECATED)
+# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+ ((major) < 4 || ((major) == 4 && (minor) <= 6))
+# elif defined(_GLIBCXX_PSEUDO_VISIBILITY)
+# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+ ((major) < 4 || ((major) == 4 && (minor) <= 5))
+# elif defined(_GLIBCXX_BEGIN_EXTERN_C)
+# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+ ((major) < 4 || ((major) == 4 && (minor) <= 4))
+# elif defined(_GLIBCXX_VISIBILITY_ATTR)
+# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+ ((major) < 4 || ((major) == 4 && (minor) <= 3))
+# elif defined(_GLIBCXX_VISIBILITY)
+# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \
+ ((major) < 4 || ((major) == 4 && (minor) <= 2))
+# else
+# error "Your version of libstdc++ is unknown to us and is likely too old."
+# endif
+# endif
+
+ // Flesh out the defines for everyone else
+# ifndef MOZ_USING_STLPORT
+# define MOZ_USING_STLPORT 0
+# define MOZ_STLPORT_VERSION_AT_LEAST(major, minor, patch) 0
+# endif
+# ifndef MOZ_USING_LIBCXX
+# define MOZ_USING_LIBCXX 0
+# endif
+# ifndef MOZ_USING_LIBSTDCXX
+# define MOZ_USING_LIBSTDCXX 0
+# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) 0
+# endif
+#endif /* __cplusplus */
+
+#endif /* mozilla_Compiler_h */
diff --git a/onlineupdate/source/update/inc/mozilla/Likely.h b/onlineupdate/source/update/inc/mozilla/Likely.h
new file mode 100644
index 000000000000..4f2160929544
--- /dev/null
+++ b/onlineupdate/source/update/inc/mozilla/Likely.h
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * MOZ_LIKELY and MOZ_UNLIKELY macros to hint to the compiler how a
+ * boolean predicate should be branch-predicted.
+ */
+
+#ifndef mozilla_Likely_h
+#define mozilla_Likely_h
+
+#if defined(__clang__) || defined(__GNUC__)
+# define MOZ_LIKELY(x) (__builtin_expect(!!(x), 1))
+# define MOZ_UNLIKELY(x) (__builtin_expect(!!(x), 0))
+#else
+# define MOZ_LIKELY(x) (!!(x))
+# define MOZ_UNLIKELY(x) (!!(x))
+#endif
+
+#endif /* mozilla_Likely_h */
diff --git a/onlineupdate/source/update/inc/mozilla/MacroArgs.h b/onlineupdate/source/update/inc/mozilla/MacroArgs.h
new file mode 100644
index 000000000000..c8b733821035
--- /dev/null
+++ b/onlineupdate/source/update/inc/mozilla/MacroArgs.h
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Implements various macros meant to ease the use of variadic macros.
+ */
+
+#ifndef mozilla_MacroArgs_h
+#define mozilla_MacroArgs_h
+
+/*
+ * MOZ_PASTE_PREFIX_AND_ARG_COUNT(aPrefix, ...) counts the number of variadic
+ * arguments and prefixes it with |aPrefix|. For example:
+ *
+ * MOZ_PASTE_PREFIX_AND_ARG_COUNT(, foo, 42) expands to 2
+ * MOZ_PASTE_PREFIX_AND_ARG_COUNT(A, foo, 42, bar) expands to A3
+ *
+ * You must pass in between 1 and 50 (inclusive) variadic arguments, past
+ * |aPrefix|. It is not legal to do
+ *
+ * MOZ_PASTE_PREFIX_AND_ARG_COUNT(prefix)
+ *
+ * (that is, pass in 0 variadic arguments). To ensure that a compile-time
+ * error occurs when these constraints are violated, use the
+ * MOZ_STATIC_ASSERT_VALID_ARG_COUNT macro with the same variaidc arguments
+ * wherever this macro is used.
+ *
+ * Passing (__VA_ARGS__, <rest of arguments>) rather than simply calling
+ * MOZ_MACROARGS_ARG_COUNT_HELPER2(__VA_ARGS__, <rest of arguments>) very
+ * carefully tiptoes around a MSVC bug where it improperly expands __VA_ARGS__
+ * as a single token in argument lists. For details, see:
+ *
+ * http://connect.microsoft.com/VisualStudio/feedback/details/380090/variadic-macro-replacement
+ * http://cplusplus.co.il/2010/07/17/variadic-macro-to-count-number-of-arguments/#comment-644
+ */
+#define MOZ_PASTE_PREFIX_AND_ARG_COUNT(aPrefix, ...) \
+ MOZ_MACROARGS_ARG_COUNT_HELPER((__VA_ARGS__, \
+ aPrefix##50, aPrefix##49, aPrefix##48, aPrefix##47, aPrefix##46, \
+ aPrefix##45, aPrefix##44, aPrefix##43, aPrefix##42, aPrefix##41, \
+ aPrefix##40, aPrefix##39, aPrefix##38, aPrefix##37, aPrefix##36, \
+ aPrefix##35, aPrefix##34, aPrefix##33, aPrefix##32, aPrefix##31, \
+ aPrefix##30, aPrefix##29, aPrefix##28, aPrefix##27, aPrefix##26, \
+ aPrefix##25, aPrefix##24, aPrefix##23, aPrefix##22, aPrefix##21, \
+ aPrefix##20, aPrefix##19, aPrefix##18, aPrefix##17, aPrefix##16, \
+ aPrefix##15, aPrefix##14, aPrefix##13, aPrefix##12, aPrefix##11, \
+ aPrefix##10, aPrefix##9, aPrefix##8, aPrefix##7, aPrefix##6, \
+ aPrefix##5, aPrefix##4, aPrefix##3, aPrefix##2, aPrefix##1, aPrefix##0))
+
+#define MOZ_MACROARGS_ARG_COUNT_HELPER(aArgs) \
+ MOZ_MACROARGS_ARG_COUNT_HELPER2 aArgs
+
+#define MOZ_MACROARGS_ARG_COUNT_HELPER2( \
+ a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
+ a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, \
+ a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, \
+ a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, \
+ a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, \
+ a51, ...) a51
+
+/*
+ * MOZ_STATIC_ASSERT_VALID_ARG_COUNT ensures that a compile-time error occurs
+ * when the argument count constraints of MOZ_PASTE_PREFIX_AND_ARG_COUNT are
+ * violated. Use this macro wherever MOZ_PASTE_PREFIX_AND_ARG_COUNT is used
+ * and pass it the same variadic arguments.
+ *
+ * This macro employs a few dirty tricks to function. To detect the zero
+ * argument case, |(__VA_ARGS__)| is stringified, sizeof-ed, and compared to
+ * what it should be in the absence of arguments.
+ *
+ * Detecting too many arguments is a little trickier. With a valid argument
+ * count and a prefix of 1, MOZ_PASTE_PREFIX_AND_ARG_COUNT expands to e.g. 14.
+ * With a prefix of 0.0, it expands to e.g. 0.04. If there are too many
+ * arguments, it expands to the first argument over the limit. If this
+ * exceeding argument is a number, the assertion will fail as there is no
+ * number than can simultaneously be both > 10 and == 0. If the exceeding
+ * argument is not a number, a compile-time error should still occur due to
+ * the operations performed on it.
+ */
+#define MOZ_MACROARGS_STRINGIFY_HELPER(x) #x
+#define MOZ_STATIC_ASSERT_VALID_ARG_COUNT(...) \
+ static_assert( \
+ sizeof(MOZ_MACROARGS_STRINGIFY_HELPER((__VA_ARGS__))) != sizeof("()") && \
+ (MOZ_PASTE_PREFIX_AND_ARG_COUNT(1, __VA_ARGS__)) > 10 && \
+ (int)(MOZ_PASTE_PREFIX_AND_ARG_COUNT(0.0, __VA_ARGS__)) == 0, \
+ "MOZ_STATIC_ASSERT_VALID_ARG_COUNT requires 1 to 50 arguments") /* ; */
+
+/*
+ * MOZ_ARGS_AFTER_N expands to its arguments excluding the first |N|
+ * arguments. For example:
+ *
+ * MOZ_ARGS_AFTER_2(a, b, c, d) expands to: c, d
+ */
+#define MOZ_ARGS_AFTER_1(a1, ...) __VA_ARGS__
+#define MOZ_ARGS_AFTER_2(a1, a2, ...) __VA_ARGS__
+
+/*
+ * MOZ_ARG_N expands to its |N|th argument.
+ */
+#define MOZ_ARG_1(a1, ...) a1
+#define MOZ_ARG_2(a1, a2, ...) a2
+
+#endif /* mozilla_MacroArgs_h */
diff --git a/onlineupdate/source/update/inc/mozilla/TypeTraits.h b/onlineupdate/source/update/inc/mozilla/TypeTraits.h
new file mode 100644
index 000000000000..47c7945a6a2d
--- /dev/null
+++ b/onlineupdate/source/update/inc/mozilla/TypeTraits.h
@@ -0,0 +1,1116 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Template-based metaprogramming and type-testing facilities. */
+
+#ifndef mozilla_TypeTraits_h
+#define mozilla_TypeTraits_h
+
+#include "mozilla/Types.h"
+
+/*
+ * These traits are approximate copies of the traits and semantics from C++11's
+ * <type_traits> header. Don't add traits not in that header! When all
+ * platforms provide that header, we can convert all users and remove this one.
+ */
+
+#include <wchar.h>
+
+namespace mozilla {
+
+/* Forward declarations. */
+
+template<typename> struct RemoveCV;
+
+/* 20.9.3 Helper classes [meta.help] */
+
+/**
+ * Helper class used as a base for various type traits, exposed publicly
+ * because <type_traits> exposes it as well.
+ */
+template<typename T, T Value>
+struct IntegralConstant
+{
+ static const T value = Value;
+ typedef T ValueType;
+ typedef IntegralConstant<T, Value> Type;
+};
+
+/** Convenient aliases. */
+typedef IntegralConstant<bool, true> TrueType;
+typedef IntegralConstant<bool, false> FalseType;
+
+/* 20.9.4 Unary type traits [meta.unary] */
+
+/* 20.9.4.1 Primary type categories [meta.unary.cat] */
+
+namespace detail {
+
+template<typename T>
+struct IsVoidHelper : FalseType {};
+
+template<>
+struct IsVoidHelper<void> : TrueType {};
+
+} // namespace detail
+
+/**
+ * IsVoid determines whether a type is void.
+ *
+ * mozilla::IsVoid<int>::value is false;
+ * mozilla::IsVoid<void>::value is true;
+ * mozilla::IsVoid<void*>::value is false;
+ * mozilla::IsVoid<volatile void>::value is true.
+ */
+template<typename T>
+struct IsVoid : detail::IsVoidHelper<typename RemoveCV<T>::Type> {};
+
+namespace detail {
+
+template <typename T>
+struct IsIntegralHelper : FalseType {};
+
+template<> struct IsIntegralHelper<char> : TrueType {};
+template<> struct IsIntegralHelper<signed char> : TrueType {};
+template<> struct IsIntegralHelper<unsigned char> : TrueType {};
+template<> struct IsIntegralHelper<short> : TrueType {};
+template<> struct IsIntegralHelper<unsigned short> : TrueType {};
+template<> struct IsIntegralHelper<int> : TrueType {};
+template<> struct IsIntegralHelper<unsigned int> : TrueType {};
+template<> struct IsIntegralHelper<long> : TrueType {};
+template<> struct IsIntegralHelper<unsigned long> : TrueType {};
+template<> struct IsIntegralHelper<long long> : TrueType {};
+template<> struct IsIntegralHelper<unsigned long long> : TrueType {};
+template<> struct IsIntegralHelper<bool> : TrueType {};
+template<> struct IsIntegralHelper<wchar_t> : TrueType {};
+#ifdef MOZ_CHAR16_IS_NOT_WCHAR
+template<> struct IsIntegralHelper<char16_t> : TrueType {};
+#endif
+
+} /* namespace detail */
+
+/**
+ * IsIntegral determines whether a type is an integral type.
+ *
+ * mozilla::IsIntegral<int>::value is true;
+ * mozilla::IsIntegral<unsigned short>::value is true;
+ * mozilla::IsIntegral<const long>::value is true;
+ * mozilla::IsIntegral<int*>::value is false;
+ * mozilla::IsIntegral<double>::value is false;
+ *
+ * Note that the behavior of IsIntegral on char16_t and char32_t is
+ * unspecified.
+ */
+template<typename T>
+struct IsIntegral : detail::IsIntegralHelper<typename RemoveCV<T>::Type>
+{};
+
+template<typename T, typename U>
+struct IsSame;
+
+namespace detail {
+
+template<typename T>
+struct IsFloatingPointHelper
+ : IntegralConstant<bool,
+ IsSame<T, float>::value ||
+ IsSame<T, double>::value ||
+ IsSame<T, long double>::value>
+{};
+
+} // namespace detail
+
+/**
+ * IsFloatingPoint determines whether a type is a floating point type (float,
+ * double, long double).
+ *
+ * mozilla::IsFloatingPoint<int>::value is false;
+ * mozilla::IsFloatingPoint<const float>::value is true;
+ * mozilla::IsFloatingPoint<long double>::value is true;
+ * mozilla::IsFloatingPoint<double*>::value is false.
+ */
+template<typename T>
+struct IsFloatingPoint
+ : detail::IsFloatingPointHelper<typename RemoveCV<T>::Type>
+{};
+
+namespace detail {
+
+template<typename T>
+struct IsArrayHelper : FalseType {};
+
+template<typename T, decltype(sizeof(1)) N>
+struct IsArrayHelper<T[N]> : TrueType {};
+
+template<typename T>
+struct IsArrayHelper<T[]> : TrueType {};
+
+} // namespace detail
+
+/**
+ * IsArray determines whether a type is an array type, of known or unknown
+ * length.
+ *
+ * mozilla::IsArray<int>::value is false;
+ * mozilla::IsArray<int[]>::value is true;
+ * mozilla::IsArray<int[5]>::value is true.
+ */
+template<typename T>
+struct IsArray : detail::IsArrayHelper<typename RemoveCV<T>::Type>
+{};
+
+namespace detail {
+
+template<typename T>
+struct IsPointerHelper : FalseType {};
+
+template<typename T>
+struct IsPointerHelper<T*> : TrueType {};
+
+} // namespace detail
+
+/**
+ * IsPointer determines whether a type is a possibly-CV-qualified pointer type
+ * (but not a pointer-to-member type).
+ *
+ * mozilla::IsPointer<struct S*>::value is true;
+ * mozilla::IsPointer<int*>::value is true;
+ * mozilla::IsPointer<int**>::value is true;
+ * mozilla::IsPointer<const int*>::value is true;
+ * mozilla::IsPointer<int* const>::value is true;
+ * mozilla::IsPointer<int* volatile>::value is true;
+ * mozilla::IsPointer<void (*)(void)>::value is true;
+ * mozilla::IsPointer<int>::value is false;
+ * mozilla::IsPointer<struct S>::value is false.
+ * mozilla::IsPointer<int(struct S::*)>::value is false
+ */
+template<typename T>
+struct IsPointer : detail::IsPointerHelper<typename RemoveCV<T>::Type>
+{};
+
+/**
+ * IsLvalueReference determines whether a type is an lvalue reference.
+ *
+ * mozilla::IsLvalueReference<struct S*>::value is false;
+ * mozilla::IsLvalueReference<int**>::value is false;
+ * mozilla::IsLvalueReference<void (*)(void)>::value is false;
+ * mozilla::IsLvalueReference<int>::value is false;
+ * mozilla::IsLvalueReference<struct S>::value is false;
+ * mozilla::IsLvalueReference<struct S*&>::value is true;
+ * mozilla::IsLvalueReference<struct S&&>::value is false.
+ */
+template<typename T>
+struct IsLvalueReference : FalseType {};
+
+template<typename T>
+struct IsLvalueReference<T&> : TrueType {};
+
+/**
+ * IsRvalueReference determines whether a type is an rvalue reference.
+ *
+ * mozilla::IsRvalueReference<struct S*>::value is false;
+ * mozilla::IsRvalueReference<int**>::value is false;
+ * mozilla::IsRvalueReference<void (*)(void)>::value is false;
+ * mozilla::IsRvalueReference<int>::value is false;
+ * mozilla::IsRvalueReference<struct S>::value is false;
+ * mozilla::IsRvalueReference<struct S*&>::value is false;
+ * mozilla::IsRvalueReference<struct S&&>::value is true.
+ */
+template<typename T>
+struct IsRvalueReference : FalseType {};
+
+template<typename T>
+struct IsRvalueReference<T&&> : TrueType {};
+
+namespace detail {
+
+// __is_enum is a supported extension across all of our supported compilers.
+template<typename T>
+struct IsEnumHelper
+ : IntegralConstant<bool, __is_enum(T)>
+{};
+
+} // namespace detail
+
+/**
+ * IsEnum determines whether a type is an enum type.
+ *
+ * mozilla::IsEnum<enum S>::value is true;
+ * mozilla::IsEnum<enum S*>::value is false;
+ * mozilla::IsEnum<int>::value is false;
+ */
+template<typename T>
+struct IsEnum
+ : detail::IsEnumHelper<typename RemoveCV<T>::Type>
+{};
+
+namespace detail {
+
+// __is_class is a supported extension across all of our supported compilers:
+// http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html
+// http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits
+// http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspx
+template<typename T>
+struct IsClassHelper
+ : IntegralConstant<bool, __is_class(T)>
+{};
+
+} // namespace detail
+
+/**
+ * IsClass determines whether a type is a class type (but not a union).
+ *
+ * struct S {};
+ * union U {};
+ * mozilla::IsClass<int>::value is false;
+ * mozilla::IsClass<const S>::value is true;
+ * mozilla::IsClass<U>::value is false;
+ */
+template<typename T>
+struct IsClass
+ : detail::IsClassHelper<typename RemoveCV<T>::Type>
+{};
+
+/* 20.9.4.2 Composite type traits [meta.unary.comp] */
+
+/**
+ * IsReference determines whether a type is an lvalue or rvalue reference.
+ *
+ * mozilla::IsReference<struct S*>::value is false;
+ * mozilla::IsReference<int**>::value is false;
+ * mozilla::IsReference<int&>::value is true;
+ * mozilla::IsReference<void (*)(void)>::value is false;
+ * mozilla::IsReference<const int&>::value is true;
+ * mozilla::IsReference<int>::value is false;
+ * mozilla::IsReference<struct S>::value is false;
+ * mozilla::IsReference<struct S&>::value is true;
+ * mozilla::IsReference<struct S*&>::value is true;
+ * mozilla::IsReference<struct S&&>::value is true.
+ */
+template<typename T>
+struct IsReference
+ : IntegralConstant<bool,
+ IsLvalueReference<T>::value || IsRvalueReference<T>::value>
+{};
+
+/**
+ * IsArithmetic determines whether a type is arithmetic. A type is arithmetic
+ * iff it is an integral type or a floating point type.
+ *
+ * mozilla::IsArithmetic<int>::value is true;
+ * mozilla::IsArithmetic<double>::value is true;
+ * mozilla::IsArithmetic<long double*>::value is false.
+ */
+template<typename T>
+struct IsArithmetic
+ : IntegralConstant<bool, IsIntegral<T>::value || IsFloatingPoint<T>::value>
+{};
+
+/* 20.9.4.3 Type properties [meta.unary.prop] */
+
+/**
+ * IsConst determines whether a type is const or not.
+ *
+ * mozilla::IsConst<int>::value is false;
+ * mozilla::IsConst<void* const>::value is true;
+ * mozilla::IsConst<const char*>::value is false.
+ */
+template<typename T>
+struct IsConst : FalseType {};
+
+template<typename T>
+struct IsConst<const T> : TrueType {};
+
+/**
+ * IsVolatile determines whether a type is volatile or not.
+ *
+ * mozilla::IsVolatile<int>::value is false;
+ * mozilla::IsVolatile<void* volatile>::value is true;
+ * mozilla::IsVolatile<volatile char*>::value is false.
+ */
+template<typename T>
+struct IsVolatile : FalseType {};
+
+template<typename T>
+struct IsVolatile<volatile T> : TrueType {};
+
+/**
+ * Traits class for identifying POD types. Until C++11 there's no automatic
+ * way to detect PODs, so for the moment this is done manually. Users may
+ * define specializations of this class that inherit from mozilla::TrueType and
+ * mozilla::FalseType (or equivalently mozilla::IntegralConstant<bool, true or
+ * false>, or conveniently from mozilla::IsPod for composite types) as needed to
+ * ensure correct IsPod behavior.
+ */
+template<typename T>
+struct IsPod : public FalseType {};
+
+template<> struct IsPod<char> : TrueType {};
+template<> struct IsPod<signed char> : TrueType {};
+template<> struct IsPod<unsigned char> : TrueType {};
+template<> struct IsPod<short> : TrueType {};
+template<> struct IsPod<unsigned short> : TrueType {};
+template<> struct IsPod<int> : TrueType {};
+template<> struct IsPod<unsigned int> : TrueType {};
+template<> struct IsPod<long> : TrueType {};
+template<> struct IsPod<unsigned long> : TrueType {};
+template<> struct IsPod<long long> : TrueType {};
+template<> struct IsPod<unsigned long long> : TrueType {};
+template<> struct IsPod<bool> : TrueType {};
+template<> struct IsPod<float> : TrueType {};
+template<> struct IsPod<double> : TrueType {};
+template<> struct IsPod<wchar_t> : TrueType {};
+#ifdef MOZ_CHAR16_IS_NOT_WCHAR
+template<> struct IsPod<char16_t> : TrueType {};
+#endif
+template<typename T> struct IsPod<T*> : TrueType {};
+
+namespace detail {
+
+// __is_empty is a supported extension across all of our supported compilers:
+// http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html
+// http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits
+// http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspx
+template<typename T>
+struct IsEmptyHelper
+ : IntegralConstant<bool, IsClass<T>::value && __is_empty(T)>
+{};
+
+} // namespace detail
+
+/**
+ * IsEmpty determines whether a type is a class (but not a union) that is empty.
+ *
+ * A class is empty iff it and all its base classes have no non-static data
+ * members (except bit-fields of length 0) and no virtual member functions, and
+ * no base class is empty or a virtual base class.
+ *
+ * Intuitively, empty classes don't have any data that has to be stored in
+ * instances of those classes. (The size of the class must still be non-zero,
+ * because distinct array elements of any type must have different addresses.
+ * However, if the Empty Base Optimization is implemented by the compiler [most
+ * compilers implement it, and in certain cases C++11 requires it], the size of
+ * a class inheriting from an empty |Base| class need not be inflated by
+ * |sizeof(Base)|.) And intuitively, non-empty classes have data members and/or
+ * vtable pointers that must be stored in each instance for proper behavior.
+ *
+ * static_assert(!mozilla::IsEmpty<int>::value, "not a class => not empty");
+ * union U1 { int x; };
+ * static_assert(!mozilla::IsEmpty<U1>::value, "not a class => not empty");
+ * struct E1 {};
+ * struct E2 { int : 0 };
+ * struct E3 : E1 {};
+ * struct E4 : E2 {};
+ * static_assert(mozilla::IsEmpty<E1>::value &&
+ * mozilla::IsEmpty<E2>::value &&
+ * mozilla::IsEmpty<E3>::value &&
+ * mozilla::IsEmpty<E4>::value,
+ * "all empty");
+ * union U2 { E1 e1; };
+ * static_assert(!mozilla::IsEmpty<U2>::value, "not a class => not empty");
+ * struct NE1 { int x; };
+ * struct NE2 : virtual E1 {};
+ * struct NE3 : E2 { virtual ~NE3() {} };
+ * struct NE4 { virtual void f() {} };
+ * static_assert(!mozilla::IsEmpty<NE1>::value &&
+ * !mozilla::IsEmpty<NE2>::value &&
+ * !mozilla::IsEmpty<NE3>::value &&
+ * !mozilla::IsEmpty<NE4>::value,
+ * "all empty");
+ */
+template<typename T>
+struct IsEmpty : detail::IsEmptyHelper<typename RemoveCV<T>::Type>
+{};
+
+
+namespace detail {
+
+template<typename T,
+ bool = IsFloatingPoint<T>::value,
+ bool = IsIntegral<T>::value,
+ typename NoCV = typename RemoveCV<T>::Type>
+struct IsSignedHelper;
+
+// Floating point is signed.
+template<typename T, typename NoCV>
+struct IsSignedHelper<T, true, false, NoCV> : TrueType {};
+
+// Integral is conditionally signed.
+template<typename T, typename NoCV>
+struct IsSignedHelper<T, false, true, NoCV>
+ : IntegralConstant<bool, bool(NoCV(-1) < NoCV(1))>
+{};
+
+// Non-floating point, non-integral is not signed.
+template<typename T, typename NoCV>
+struct IsSignedHelper<T, false, false, NoCV> : FalseType {};
+
+} // namespace detail
+
+/**
+ * IsSigned determines whether a type is a signed arithmetic type. |char| is
+ * considered a signed type if it has the same representation as |signed char|.
+ *
+ * mozilla::IsSigned<int>::value is true;
+ * mozilla::IsSigned<const unsigned int>::value is false;
+ * mozilla::IsSigned<unsigned char>::value is false;
+ * mozilla::IsSigned<float>::value is true.
+ */
+template<typename T>
+struct IsSigned : detail::IsSignedHelper<T> {};
+
+namespace detail {
+
+template<typename T,
+ bool = IsFloatingPoint<T>::value,
+ bool = IsIntegral<T>::value,
+ typename NoCV = typename RemoveCV<T>::Type>
+struct IsUnsignedHelper;
+
+// Floating point is not unsigned.
+template<typename T, typename NoCV>
+struct IsUnsignedHelper<T, true, false, NoCV> : FalseType {};
+
+// Integral is conditionally unsigned.
+template<typename T, typename NoCV>
+struct IsUnsignedHelper<T, false, true, NoCV>
+ : IntegralConstant<bool,
+ (IsSame<NoCV, bool>::value || bool(NoCV(1) < NoCV(-1)))>
+{};
+
+// Non-floating point, non-integral is not unsigned.
+template<typename T, typename NoCV>
+struct IsUnsignedHelper<T, false, false, NoCV> : FalseType {};
+
+} // namespace detail
+
+/**
+ * IsUnsigned determines whether a type is an unsigned arithmetic type.
+ *
+ * mozilla::IsUnsigned<int>::value is false;
+ * mozilla::IsUnsigned<const unsigned int>::value is true;
+ * mozilla::IsUnsigned<unsigned char>::value is true;
+ * mozilla::IsUnsigned<float>::value is false.
+ */
+template<typename T>
+struct IsUnsigned : detail::IsUnsignedHelper<T> {};
+
+/* 20.9.5 Type property queries [meta.unary.prop.query] */
+
+/* 20.9.6 Relationships between types [meta.rel] */
+
+/**
+ * IsSame tests whether two types are the same type.
+ *
+ * mozilla::IsSame<int, int>::value is true;
+ * mozilla::IsSame<int*, int*>::value is true;
+ * mozilla::IsSame<int, unsigned int>::value is false;
+ * mozilla::IsSame<void, void>::value is true;
+ * mozilla::IsSame<const int, int>::value is false;
+ * mozilla::IsSame<struct S, struct S>::value is true.
+ */
+template<typename T, typename U>
+struct IsSame : FalseType {};
+
+template<typename T>
+struct IsSame<T, T> : TrueType {};
+
+namespace detail {
+
+#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
+
+template<class Base, class Derived>
+struct BaseOfTester : IntegralConstant<bool, __is_base_of(Base, Derived)> {};
+
+#else
+
+// The trickery used to implement IsBaseOf here makes it possible to use it for
+// the cases of private and multiple inheritance. This code was inspired by the
+// sample code here:
+//
+// http://stackoverflow.com/questions/2910979/how-is-base-of-works
+template<class Base, class Derived>
+struct BaseOfHelper
+{
+public:
+ operator Base*() const;
+ operator Derived*();
+};
+
+template<class Base, class Derived>
+struct BaseOfTester
+{
+private:
+ template<class T>
+ static char test(Derived*, T);
+ static int test(Base*, int);
+
+public:
+ static const bool value =
+ sizeof(test(BaseOfHelper<Base, Derived>(), int())) == sizeof(char);
+};
+
+template<class Base, class Derived>
+struct BaseOfTester<Base, const Derived>
+{
+private:
+ template<class T>
+ static char test(Derived*, T);
+ static int test(Base*, int);
+
+public:
+ static const bool value =
+ sizeof(test(BaseOfHelper<Base, Derived>(), int())) == sizeof(char);
+};
+
+template<class Base, class Derived>
+struct BaseOfTester<Base&, Derived&> : FalseType {};
+
+template<class Type>
+struct BaseOfTester<Type, Type> : TrueType {};
+
+template<class Type>
+struct BaseOfTester<Type, const Type> : TrueType {};
+
+#endif
+
+} /* namespace detail */
+
+/*
+ * IsBaseOf allows to know whether a given class is derived from another.
+ *
+ * Consider the following class definitions:
+ *
+ * class A {};
+ * class B : public A {};
+ * class C {};
+ *
+ * mozilla::IsBaseOf<A, B>::value is true;
+ * mozilla::IsBaseOf<A, C>::value is false;
+ */
+template<class Base, class Derived>
+struct IsBaseOf
+ : IntegralConstant<bool, detail::BaseOfTester<Base, Derived>::value>
+{};
+
+namespace detail {
+
+template<typename From, typename To>
+struct ConvertibleTester
+{
+private:
+ static From create();
+
+ template<typename From1, typename To1>
+ static char test(To to);
+
+ template<typename From1, typename To1>
+ static int test(...);
+
+public:
+ static const bool value =
+ sizeof(test<From, To>(create())) == sizeof(char);
+};
+
+} // namespace detail
+
+/**
+ * IsConvertible determines whether a value of type From will implicitly convert
+ * to a value of type To. For example:
+ *
+ * struct A {};
+ * struct B : public A {};
+ * struct C {};
+ *
+ * mozilla::IsConvertible<A, A>::value is true;
+ * mozilla::IsConvertible<A*, A*>::value is true;
+ * mozilla::IsConvertible<B, A>::value is true;
+ * mozilla::IsConvertible<B*, A*>::value is true;
+ * mozilla::IsConvertible<C, A>::value is false;
+ * mozilla::IsConvertible<A, C>::value is false;
+ * mozilla::IsConvertible<A*, C*>::value is false;
+ * mozilla::IsConvertible<C*, A*>::value is false.
+ *
+ * For obscure reasons, you can't use IsConvertible when the types being tested
+ * are related through private inheritance, and you'll get a compile error if
+ * you try. Just don't do it!
+ *
+ * Note - we need special handling for void, which ConvertibleTester doesn't
+ * handle. The void handling here doesn't handle const/volatile void correctly,
+ * which could be easily fixed if the need arises.
+ */
+template<typename From, typename To>
+struct IsConvertible
+ : IntegralConstant<bool, detail::ConvertibleTester<From, To>::value>
+{};
+
+template<typename B>
+struct IsConvertible<void, B>
+ : IntegralConstant<bool, IsVoid<B>::value>
+{};
+
+template<typename A>
+struct IsConvertible<A, void>
+ : IntegralConstant<bool, IsVoid<A>::value>
+{};
+
+template<>
+struct IsConvertible<void, void>
+ : TrueType
+{};
+
+/* 20.9.7 Transformations between types [meta.trans] */
+
+/* 20.9.7.1 Const-volatile modifications [meta.trans.cv] */
+
+/**
+ * RemoveConst removes top-level const qualifications on a type.
+ *
+ * mozilla::RemoveConst<int>::Type is int;
+ * mozilla::RemoveConst<const int>::Type is int;
+ * mozilla::RemoveConst<const int*>::Type is const int*;
+ * mozilla::RemoveConst<int* const>::Type is int*.
+ */
+template<typename T>
+struct RemoveConst
+{
+ typedef T Type;
+};
+
+template<typename T>
+struct RemoveConst<const T>
+{
+ typedef T Type;
+};
+
+/**
+ * RemoveVolatile removes top-level volatile qualifications on a type.
+ *
+ * mozilla::RemoveVolatile<int>::Type is int;
+ * mozilla::RemoveVolatile<volatile int>::Type is int;
+ * mozilla::RemoveVolatile<volatile int*>::Type is volatile int*;
+ * mozilla::RemoveVolatile<int* volatile>::Type is int*.
+ */
+template<typename T>
+struct RemoveVolatile
+{
+ typedef T Type;
+};
+
+template<typename T>
+struct RemoveVolatile<volatile T>
+{
+ typedef T Type;
+};
+
+/**
+ * RemoveCV removes top-level const and volatile qualifications on a type.
+ *
+ * mozilla::RemoveCV<int>::Type is int;
+ * mozilla::RemoveCV<const int>::Type is int;
+ * mozilla::RemoveCV<volatile int>::Type is int;
+ * mozilla::RemoveCV<int* const volatile>::Type is int*.
+ */
+template<typename T>
+struct RemoveCV
+{
+ typedef typename RemoveConst<typename RemoveVolatile<T>::Type>::Type Type;
+};
+
+/* 20.9.7.2 Reference modifications [meta.trans.ref] */
+
+/**
+ * Converts reference types to the underlying types.
+ *
+ * mozilla::RemoveReference<T>::Type is T;
+ * mozilla::RemoveReference<T&>::Type is T;
+ * mozilla::RemoveReference<T&&>::Type is T;
+ */
+
+template<typename T>
+struct RemoveReference
+{
+ typedef T Type;
+};
+
+template<typename T>
+struct RemoveReference<T&>
+{
+ typedef T Type;
+};
+
+template<typename T>
+struct RemoveReference<T&&>
+{
+ typedef T Type;
+};
+
+template<bool Condition, typename A, typename B>
+struct Conditional;
+
+namespace detail {
+
+enum Voidness { TIsVoid, TIsNotVoid };
+
+template<typename T, Voidness V = IsVoid<T>::value ? TIsVoid : TIsNotVoid>
+struct AddLvalueReferenceHelper;
+
+template<typename T>
+struct AddLvalueReferenceHelper<T, TIsVoid>
+{
+ typedef void Type;
+};
+
+template<typename T>
+struct AddLvalueReferenceHelper<T, TIsNotVoid>
+{
+ typedef T& Type;
+};
+
+} // namespace detail
+
+/**
+ * AddLvalueReference adds an lvalue & reference to T if one isn't already
+ * present. (Note: adding an lvalue reference to an rvalue && reference in
+ * essence replaces the && with a &&, per C+11 reference collapsing rules. For
+ * example, int&& would become int&.)
+ *
+ * The final computed type will only *not* be an lvalue reference if T is void.
+ *
+ * mozilla::AddLvalueReference<int>::Type is int&;
+ * mozilla::AddLvalueRference<volatile int&>::Type is volatile int&;
+ * mozilla::AddLvalueReference<void*>::Type is void*&;
+ * mozilla::AddLvalueReference<void>::Type is void;
+ * mozilla::AddLvalueReference<struct S&&>::Type is struct S&.
+ */
+template<typename T>
+struct AddLvalueReference
+ : detail::AddLvalueReferenceHelper<T>
+{};
+
+namespace detail {
+
+template<typename T, Voidness V = IsVoid<T>::value ? TIsVoid : TIsNotVoid>
+struct AddRvalueReferenceHelper;
+
+template<typename T>
+struct AddRvalueReferenceHelper<T, TIsVoid>
+{
+ typedef void Type;
+};
+
+template<typename T>
+struct AddRvalueReferenceHelper<T, TIsNotVoid>
+{
+ typedef T&& Type;
+};
+
+} // namespace detail
+
+/**
+ * AddRvalueReference adds an rvalue && reference to T if one isn't already
+ * present. (Note: adding an rvalue reference to an lvalue & reference in
+ * essence keeps the &, per C+11 reference collapsing rules. For example,
+ * int& would remain int&.)
+ *
+ * The final computed type will only *not* be a reference if T is void.
+ *
+ * mozilla::AddRvalueReference<int>::Type is int&&;
+ * mozilla::AddRvalueRference<volatile int&>::Type is volatile int&;
+ * mozilla::AddRvalueRference<const int&&>::Type is const int&&;
+ * mozilla::AddRvalueReference<void*>::Type is void*&&;
+ * mozilla::AddRvalueReference<void>::Type is void;
+ * mozilla::AddRvalueReference<struct S&>::Type is struct S&.
+ */
+template<typename T>
+struct AddRvalueReference
+ : detail::AddRvalueReferenceHelper<T>
+{};
+
+/* 20.2.4 Function template declval [declval] */
+
+/**
+ * DeclVal simplifies the definition of expressions which occur as unevaluated
+ * operands. It converts T to a reference type, making it possible to use in
+ * decltype expressions even if T does not have a default constructor, e.g.:
+ * decltype(DeclVal<TWithNoDefaultConstructor>().foo())
+ */
+template<typename T>
+typename AddRvalueReference<T>::Type DeclVal();
+
+/* 20.9.7.3 Sign modifications [meta.trans.sign] */
+
+template<bool B, typename T = void>
+struct EnableIf;
+
+namespace detail {
+
+template<bool MakeConst, typename T>
+struct WithC : Conditional<MakeConst, const T, T>
+{};
+
+template<bool MakeVolatile, typename T>
+struct WithV : Conditional<MakeVolatile, volatile T, T>
+{};
+
+
+template<bool MakeConst, bool MakeVolatile, typename T>
+struct WithCV : WithC<MakeConst, typename WithV<MakeVolatile, T>::Type>
+{};
+
+template<typename T>
+struct CorrespondingSigned;
+
+template<>
+struct CorrespondingSigned<char> { typedef signed char Type; };
+template<>
+struct CorrespondingSigned<unsigned char> { typedef signed char Type; };
+template<>
+struct CorrespondingSigned<unsigned short> { typedef short Type; };
+template<>
+struct CorrespondingSigned<unsigned int> { typedef int Type; };
+template<>
+struct CorrespondingSigned<unsigned long> { typedef long Type; };
+template<>
+struct CorrespondingSigned<unsigned long long> { typedef long long Type; };
+
+template<typename T,
+ typename CVRemoved = typename RemoveCV<T>::Type,
+ bool IsSignedIntegerType = IsSigned<CVRemoved>::value &&
+ !IsSame<char, CVRemoved>::value>
+struct MakeSigned;
+
+template<typename T, typename CVRemoved>
+struct MakeSigned<T, CVRemoved, true>
+{
+ typedef T Type;
+};
+
+template<typename T, typename CVRemoved>
+struct MakeSigned<T, CVRemoved, false>
+ : WithCV<IsConst<T>::value, IsVolatile<T>::value,
+ typename CorrespondingSigned<CVRemoved>::Type>
+{};
+
+} // namespace detail
+
+/**
+ * MakeSigned produces the corresponding signed integer type for a given
+ * integral type T, with the const/volatile qualifiers of T. T must be a
+ * possibly-const/volatile-qualified integral type that isn't bool.
+ *
+ * If T is already a signed integer type (not including char!), then T is
+ * produced.
+ *
+ * Otherwise, if T is an unsigned integer type, the signed variety of T, with
+ * T's const/volatile qualifiers, is produced.
+ *
+ * Otherwise, the integral type of the same size as T, with the lowest rank,
+ * with T's const/volatile qualifiers, is produced. (This basically only acts
+ * to produce signed char when T = char.)
+ *
+ * mozilla::MakeSigned<unsigned long>::Type is signed long;
+ * mozilla::MakeSigned<volatile int>::Type is volatile int;
+ * mozilla::MakeSigned<const unsigned short>::Type is const signed short;
+ * mozilla::MakeSigned<const char>::Type is const signed char;
+ * mozilla::MakeSigned<bool> is an error;
+ * mozilla::MakeSigned<void*> is an error.
+ */
+template<typename T>
+struct MakeSigned
+ : EnableIf<IsIntegral<T>::value &&
+ !IsSame<bool, typename RemoveCV<T>::Type>::value,
+ typename detail::MakeSigned<T>
+ >::Type
+{};
+
+namespace detail {
+
+template<typename T>
+struct CorrespondingUnsigned;
+
+template<>
+struct CorrespondingUnsigned<char> { typedef unsigned char Type; };
+template<>
+struct CorrespondingUnsigned<signed char> { typedef unsigned char Type; };
+template<>
+struct CorrespondingUnsigned<short> { typedef unsigned short Type; };
+template<>
+struct CorrespondingUnsigned<int> { typedef unsigned int Type; };
+template<>
+struct CorrespondingUnsigned<long> { typedef unsigned long Type; };
+template<>
+struct CorrespondingUnsigned<long long> { typedef unsigned long long Type; };
+
+
+template<typename T,
+ typename CVRemoved = typename RemoveCV<T>::Type,
+ bool IsUnsignedIntegerType = IsUnsigned<CVRemoved>::value &&
+ !IsSame<char, CVRemoved>::value>
+struct MakeUnsigned;
+
+template<typename T, typename CVRemoved>
+struct MakeUnsigned<T, CVRemoved, true>
+{
+ typedef T Type;
+};
+
+template<typename T, typename CVRemoved>
+struct MakeUnsigned<T, CVRemoved, false>
+ : WithCV<IsConst<T>::value, IsVolatile<T>::value,
+ typename CorrespondingUnsigned<CVRemoved>::Type>
+{};
+
+} // namespace detail
+
+/**
+ * MakeUnsigned produces the corresponding unsigned integer type for a given
+ * integral type T, with the const/volatile qualifiers of T. T must be a
+ * possibly-const/volatile-qualified integral type that isn't bool.
+ *
+ * If T is already an unsigned integer type (not including char!), then T is
+ * produced.
+ *
+ * Otherwise, if T is an signed integer type, the unsigned variety of T, with
+ * T's const/volatile qualifiers, is produced.
+ *
+ * Otherwise, the unsigned integral type of the same size as T, with the lowest
+ * rank, with T's const/volatile qualifiers, is produced. (This basically only
+ * acts to produce unsigned char when T = char.)
+ *
+ * mozilla::MakeUnsigned<signed long>::Type is unsigned long;
+ * mozilla::MakeUnsigned<volatile unsigned int>::Type is volatile unsigned int;
+ * mozilla::MakeUnsigned<const signed short>::Type is const unsigned short;
+ * mozilla::MakeUnsigned<const char>::Type is const unsigned char;
+ * mozilla::MakeUnsigned<bool> is an error;
+ * mozilla::MakeUnsigned<void*> is an error.
+ */
+template<typename T>
+struct MakeUnsigned
+ : EnableIf<IsIntegral<T>::value &&
+ !IsSame<bool, typename RemoveCV<T>::Type>::value,
+ typename detail::MakeUnsigned<T>
+ >::Type
+{};
+
+/* 20.9.7.4 Array modifications [meta.trans.arr] */
+
+/**
+ * RemoveExtent produces either the type of the elements of the array T, or T
+ * itself.
+ *
+ * mozilla::RemoveExtent<int>::Type is int;
+ * mozilla::RemoveExtent<const int[]>::Type is const int;
+ * mozilla::RemoveExtent<volatile int[5]>::Type is volatile int;
+ * mozilla::RemoveExtent<long[][17]>::Type is long[17].
+ */
+template<typename T>
+struct RemoveExtent
+{
+ typedef T Type;
+};
+
+template<typename T>
+struct RemoveExtent<T[]>
+{
+ typedef T Type;
+};
+
+template<typename T, decltype(sizeof(1)) N>
+struct RemoveExtent<T[N]>
+{
+ typedef T Type;
+};
+
+/* 20.9.7.5 Pointer modifications [meta.trans.ptr] */
+
+namespace detail {
+
+template<typename T, typename CVRemoved>
+struct RemovePointerHelper
+{
+ typedef T Type;
+};
+
+template<typename T, typename Pointee>
+struct RemovePointerHelper<T, Pointee*>
+{
+ typedef Pointee Type;
+};
+
+} // namespac detail
+
+/**
+ * Produces the pointed-to type if a pointer is provided, else returns the input
+ * type. Note that this does not dereference pointer-to-member pointers.
+ *
+ * struct S { bool m; void f(); };
+ * mozilla::RemovePointer<int>::Type is int;
+ * mozilla::RemovePointer<int*>::Type is int;
+ * mozilla::RemovePointer<int* const>::Type is int;
+ * mozilla::RemovePointer<int* volatile>::Type is int;
+ * mozilla::RemovePointer<const long*>::Type is const long;
+ * mozilla::RemovePointer<void* const>::Type is void;
+ * mozilla::RemovePointer<void (S::*)()>::Type is void (S::*)();
+ * mozilla::RemovePointer<void (*)()>::Type is void();
+ * mozilla::RemovePointer<bool S::*>::Type is bool S::*.
+ */
+template<typename T>
+struct RemovePointer
+ : detail::RemovePointerHelper<T, typename RemoveCV<T>::Type>
+{};
+
+/* 20.9.7.6 Other transformations [meta.trans.other] */
+
+/**
+ * EnableIf is a struct containing a typedef of T if and only if B is true.
+ *
+ * mozilla::EnableIf<true, int>::Type is int;
+ * mozilla::EnableIf<false, int>::Type is a compile-time error.
+ *
+ * Use this template to implement SFINAE-style (Substitution Failure Is not An
+ * Error) requirements. For example, you might use it to impose a restriction
+ * on a template parameter:
+ *
+ * template<typename T>
+ * class PodVector // vector optimized to store POD (memcpy-able) types
+ * {
+ * EnableIf<IsPod<T>::value, T>::Type* vector;
+ * size_t length;
+ * ...
+ * };
+ */
+template<bool B, typename T>
+struct EnableIf
+{};
+
+template<typename T>
+struct EnableIf<true, T>
+{
+ typedef T Type;
+};
+
+/**
+ * Conditional selects a class between two, depending on a given boolean value.
+ *
+ * mozilla::Conditional<true, A, B>::Type is A;
+ * mozilla::Conditional<false, A, B>::Type is B;
+ */
+template<bool Condition, typename A, typename B>
+struct Conditional
+{
+ typedef A Type;
+};
+
+template<class A, class B>
+struct Conditional<false, A, B>
+{
+ typedef B Type;
+};
+
+} /* namespace mozilla */
+
+#endif /* mozilla_TypeTraits_h */
diff --git a/onlineupdate/source/update/inc/mozilla/Types.h b/onlineupdate/source/update/inc/mozilla/Types.h
new file mode 100644
index 000000000000..a5d936389d99
--- /dev/null
+++ b/onlineupdate/source/update/inc/mozilla/Types.h
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* mfbt foundational types and macros. */
+
+#ifndef mozilla_Types_h
+#define mozilla_Types_h
+
+/*
+ * This header must be valid C and C++, includable by code embedding either
+ * SpiderMonkey or Gecko.
+ */
+
+/* Expose all <stdint.h> types and size_t. */
+#include <stddef.h>
+#include <stdint.h>
+
+/* Implement compiler and linker macros needed for APIs. */
+
+/*
+ * MOZ_EXPORT is used to declare and define a symbol or type which is externally
+ * visible to users of the current library. It encapsulates various decorations
+ * needed to properly export the method's symbol.
+ *
+ * api.h:
+ * extern MOZ_EXPORT int MeaningOfLife(void);
+ * extern MOZ_EXPORT int LuggageCombination;
+ *
+ * api.c:
+ * int MeaningOfLife(void) { return 42; }
+ * int LuggageCombination = 12345;
+ *
+ * If you are merely sharing a method across files, just use plain |extern|.
+ * These macros are designed for use by library interfaces -- not for normal
+ * methods or data used cross-file.
+ */
+#if defined(WIN32)
+# define MOZ_EXPORT __declspec(dllexport)
+#else /* Unix */
+# ifdef HAVE_VISIBILITY_ATTRIBUTE
+# define MOZ_EXPORT __attribute__((visibility("default")))
+# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+# define MOZ_EXPORT __global
+# else
+# define MOZ_EXPORT /* nothing */
+# endif
+#endif
+
+
+/*
+ * Whereas implementers use MOZ_EXPORT to declare and define library symbols,
+ * users use MOZ_IMPORT_API and MOZ_IMPORT_DATA to access them. Most often the
+ * implementer of the library will expose an API macro which expands to either
+ * the export or import version of the macro, depending upon the compilation
+ * mode.
+ */
+#ifdef _WIN32
+# if defined(__MWERKS__)
+# define MOZ_IMPORT_API /* nothing */
+# else
+# define MOZ_IMPORT_API __declspec(dllimport)
+# endif
+#else
+# define MOZ_IMPORT_API MOZ_EXPORT
+#endif
+
+#if defined(_WIN32) && !defined(__MWERKS__)
+# define MOZ_IMPORT_DATA __declspec(dllimport)
+#else
+# define MOZ_IMPORT_DATA MOZ_EXPORT
+#endif
+
+/*
+ * Consistent with the above comment, the MFBT_API and MFBT_DATA macros expose
+ * export mfbt declarations when building mfbt, and they expose import mfbt
+ * declarations when using mfbt.
+ */
+#if defined(IMPL_MFBT)
+# define MFBT_API MOZ_EXPORT
+# define MFBT_DATA MOZ_EXPORT
+#else
+ /*
+ * On linux mozglue is linked in the program and we link libxul.so with
+ * -z,defs. Normally that causes the linker to reject undefined references in
+ * libxul.so, but as a loophole it allows undefined references to weak
+ * symbols. We add the weak attribute to the import version of the MFBT API
+ * macros to exploit this.
+ */
+# if defined(MOZ_GLUE_IN_PROGRAM) && !defined(MOZILLA_XPCOMRT_API)
+# define MFBT_API __attribute__((weak)) MOZ_IMPORT_API
+# define MFBT_DATA __attribute__((weak)) MOZ_IMPORT_DATA
+# else
+# define MFBT_API MOZ_IMPORT_API
+# define MFBT_DATA MOZ_IMPORT_DATA
+# endif
+#endif
+
+/*
+ * C symbols in C++ code must be declared immediately within |extern "C"|
+ * blocks. However, in C code, they need not be declared specially. This
+ * difference is abstracted behind the MOZ_BEGIN_EXTERN_C and MOZ_END_EXTERN_C
+ * macros, so that the user need not know whether he is being used in C or C++
+ * code.
+ *
+ * MOZ_BEGIN_EXTERN_C
+ *
+ * extern MOZ_EXPORT int MostRandomNumber(void);
+ * ...other declarations...
+ *
+ * MOZ_END_EXTERN_C
+ *
+ * This said, it is preferable to just use |extern "C"| in C++ header files for
+ * its greater clarity.
+ */
+#ifdef __cplusplus
+# define MOZ_BEGIN_EXTERN_C extern "C" {
+# define MOZ_END_EXTERN_C }
+#else
+# define MOZ_BEGIN_EXTERN_C
+# define MOZ_END_EXTERN_C
+#endif
+
+/*
+ * GCC's typeof is available when decltype is not.
+ */
+#if defined(__GNUC__) && defined(__cplusplus) && \
+ !defined(__GXX_EXPERIMENTAL_CXX0X__) && __cplusplus < 201103L
+# define decltype __typeof__
+#endif
+
+#endif /* mozilla_Types_h */
diff --git a/onlineupdate/source/update/inc/mozilla/nsTraceRefcnt.h b/onlineupdate/source/update/inc/mozilla/nsTraceRefcnt.h
new file mode 100644
index 000000000000..c5b1de7e806a
--- /dev/null
+++ b/onlineupdate/source/update/inc/mozilla/nsTraceRefcnt.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsTraceRefcnt_h___
+#define nsTraceRefcnt_h___
+
+#include <stdio.h> // for FILE
+#include "nscore.h"
+
+class nsTraceRefcnt
+{
+public:
+ static void Shutdown();
+
+ enum StatisticsType {
+ ALL_STATS,
+ NEW_STATS
+ };
+
+ static nsresult DumpStatistics(StatisticsType aType = ALL_STATS,
+ FILE* aOut = 0);
+
+ static void ResetStatistics();
+
+ static void DemangleSymbol(const char* aSymbol, char* aBuffer, int aBufLen);
+
+ static void WalkTheStack(FILE* aStream);
+
+ /**
+ * This is a variant of |WalkTheStack| that uses |CodeAddressService| to cache
+ * the results of |NS_DescribeCodeAddress|. If |WalkTheStackCached| is being
+ * called frequently, it will be a few orders of magnitude faster than
+ * |WalkTheStack|. However, the cache uses a lot of memory, which can cause
+ * OOM crashes. Therefore, this should only be used for things like refcount
+ * logging which walk the stack extremely frequently.
+ */
+ static void WalkTheStackCached(FILE* aStream);
+
+ /**
+ * Tell nsTraceRefcnt whether refcounting, allocation, and destruction
+ * activity is legal. This is used to trigger assertions for any such
+ * activity that occurs because of static constructors or destructors.
+ */
+ static void SetActivityIsLegal(bool aLegal);
+};
+
+#define NS_TRACE_REFCNT_CONTRACTID "@mozilla.org/xpcom/trace-refcnt;1"
+#define NS_TRACE_REFCNT_CID \
+{ /* e3e7511e-a395-4924-94b1-d527861cded4 */ \
+ 0xe3e7511e, \
+ 0xa395, \
+ 0x4924, \
+ {0x94, 0xb1, 0xd5, 0x27, 0x86, 0x1c, 0xde, 0xd4} \
+} \
+
+////////////////////////////////////////////////////////////////////////////////
+// And now for that utility that you've all been asking for...
+
+extern "C" void
+NS_MeanAndStdDev(double aNumberOfValues,
+ double aSumOfValues, double aSumOfSquaredValues,
+ double* aMeanResult, double* aStdDevResult);
+
+////////////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/onlineupdate/source/update/src/Makefile.in b/onlineupdate/source/update/src/Makefile.in
new file mode 100644
index 000000000000..1da582e5be03
--- /dev/null
+++ b/onlineupdate/source/update/src/Makefile.in
@@ -0,0 +1,13 @@
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This makefile just builds support for reading archives.
+
+include $(topsrcdir)/config/rules.mk
+
+# The intermediate (.ii/.s) files for host and target can have the same name...
+# disable parallel builds
+.NOTPARALLEL:
diff --git a/onlineupdate/source/update/src/mar.h b/onlineupdate/source/update/src/mar.h
new file mode 100644
index 000000000000..0e9dc1f137bd
--- /dev/null
+++ b/onlineupdate/source/update/src/mar.h
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MAR_H__
+#define MAR_H__
+
+#include "mozilla/Assertions.h"
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* We have a MAX_SIGNATURES limit so that an invalid MAR will never
+ * waste too much of either updater's or signmar's time.
+ * It is also used at various places internally and will affect memory usage.
+ * If you want to increase this value above 9 then you need to adjust parsing
+ * code in tool/mar.c.
+*/
+#define MAX_SIGNATURES 8
+#ifdef __cplusplus
+static_assert(MAX_SIGNATURES <= 9, "too many signatures");
+#else
+MOZ_STATIC_ASSERT(MAX_SIGNATURES <= 9, "too many signatures");
+#endif
+
+struct ProductInformationBlock {
+ const char *MARChannelID;
+ const char *productVersion;
+};
+
+/**
+ * The MAR item data structure.
+ */
+typedef struct MarItem_ {
+ struct MarItem_ *next; /* private field */
+ uint32_t offset; /* offset into archive */
+ uint32_t length; /* length of data in bytes */
+ uint32_t flags; /* contains file mode bits */
+ char name[1]; /* file path */
+} MarItem;
+
+#define TABLESIZE 256
+
+struct MarFile_ {
+ FILE *fp;
+ MarItem *item_table[TABLESIZE];
+};
+
+typedef struct MarFile_ MarFile;
+
+/**
+ * Signature of callback function passed to mar_enum_items.
+ * @param mar The MAR file being visited.
+ * @param item The MAR item being visited.
+ * @param data The data parameter passed by the caller of mar_enum_items.
+ * @return A non-zero value to stop enumerating.
+ */
+typedef int (* MarItemCallback)(MarFile *mar, const MarItem *item, void *data);
+
+/**
+ * Open a MAR file for reading.
+ * @param path Specifies the path to the MAR file to open. This path must
+ * be compatible with fopen.
+ * @return NULL if an error occurs.
+ */
+MarFile *mar_open(const char *path);
+
+#ifdef XP_WIN
+MarFile *mar_wopen(const wchar_t *path);
+#endif
+
+/**
+ * Close a MAR file that was opened using mar_open.
+ * @param mar The MarFile object to close.
+ */
+void mar_close(MarFile *mar);
+
+/**
+ * Find an item in the MAR file by name.
+ * @param mar The MarFile object to query.
+ * @param item The name of the item to query.
+ * @return A const reference to a MAR item or NULL if not found.
+ */
+const MarItem *mar_find_item(MarFile *mar, const char *item);
+
+/**
+ * Enumerate all MAR items via callback function.
+ * @param mar The MAR file to enumerate.
+ * @param callback The function to call for each MAR item.
+ * @param data A caller specified value that is passed along to the
+ * callback function.
+ * @return 0 if the enumeration ran to completion. Otherwise, any
+ * non-zero return value from the callback is returned.
+ */
+int mar_enum_items(MarFile *mar, MarItemCallback callback, void *data);
+
+/**
+ * Read from MAR item at given offset up to bufsize bytes.
+ * @param mar The MAR file to read.
+ * @param item The MAR item to read.
+ * @param offset The byte offset relative to the start of the item.
+ * @param buf A pointer to a buffer to copy the data into.
+ * @param bufsize The length of the buffer to copy the data into.
+ * @return The number of bytes written or a negative value if an
+ * error occurs.
+ */
+int mar_read(MarFile *mar, const MarItem *item, int offset, char *buf,
+ int bufsize);
+
+/**
+ * Create a MAR file from a set of files.
+ * @param dest The path to the file to create. This path must be
+ * compatible with fopen.
+ * @param numfiles The number of files to store in the archive.
+ * @param files The list of null-terminated file paths. Each file
+ * path must be compatible with fopen.
+ * @param infoBlock The information to store in the product information block.
+ * @return A non-zero value if an error occurs.
+ */
+int mar_create(const char *dest,
+ int numfiles,
+ char **files,
+ struct ProductInformationBlock *infoBlock);
+
+/**
+ * Extract a MAR file to the current working directory.
+ * @param path The path to the MAR file to extract. This path must be
+ * compatible with fopen.
+ * @return A non-zero value if an error occurs.
+ */
+int mar_extract(const char *path);
+
+#define MAR_MAX_CERT_SIZE (16*1024) // Way larger than necessary
+
+/* Read the entire file (not a MAR file) into a newly-allocated buffer.
+ * This function does not write to stderr. Instead, the caller should
+ * write whatever error messages it sees fit. The caller must free the returned
+ * buffer using free().
+ *
+ * @param filePath The path to the file that should be read.
+ * @param maxSize The maximum valid file size.
+ * @param data On success, *data will point to a newly-allocated buffer
+ * with the file's contents in it.
+ * @param size On success, *size will be the size of the created buffer.
+ *
+ * @return 0 on success, -1 on error
+ */
+int mar_read_entire_file(const char * filePath,
+ uint32_t maxSize,
+ /*out*/ const uint8_t * *data,
+ /*out*/ uint32_t *size);
+
+/**
+ * Verifies a MAR file by verifying each signature with the corresponding
+ * certificate. That is, the first signature will be verified using the first
+ * certificate given, the second signature will be verified using the second
+ * certificate given, etc. The signature count must exactly match the number of
+ * certificates given, and all signature verifications must succeed.
+ * We do not check that the certificate was issued by any trusted authority.
+ * We assume it to be self-signed. We do not check whether the certificate
+ * is valid for this usage.
+ *
+ * @param mar The already opened MAR file.
+ * @param certData Pointer to the first element in an array of certificate
+ * file data.
+ * @param certDataSizes Pointer to the first element in an array for size of
+ * the cert data.
+ * @param certCount The number of elements in certData and certDataSizes
+ * @return 0 on success
+ * a negative number if there was an error
+ * a positive number if the signature does not verify
+ */
+int mar_verify_signatures(MarFile *mar,
+ const uint8_t * const *certData,
+ const uint32_t *certDataSizes,
+ uint32_t certCount);
+
+/**
+ * Reads the product info block from the MAR file's additional block section.
+ * The caller is responsible for freeing the fields in infoBlock
+ * if the return is successful.
+ *
+ * @param infoBlock Out parameter for where to store the result to
+ * @return 0 on success, -1 on failure
+*/
+int
+mar_read_product_info_block(MarFile *mar,
+ struct ProductInformationBlock *infoBlock);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MAR_H__ */
diff --git a/onlineupdate/source/update/src/mar_cmdline.h b/onlineupdate/source/update/src/mar_cmdline.h
new file mode 100644
index 000000000000..ef6867f06fc3
--- /dev/null
+++ b/onlineupdate/source/update/src/mar_cmdline.h
@@ -0,0 +1,110 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MAR_CMDLINE_H__
+#define MAR_CMDLINE_H__
+
+/* We use NSPR here just to import the definition of uint32_t */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ProductInformationBlock;
+
+/**
+ * Determines MAR file information.
+ *
+ * @param path The path of the MAR file to check.
+ * @param hasSignatureBlock Optional out parameter specifying if the MAR
+ * file has a signature block or not.
+ * @param numSignatures Optional out parameter for storing the number
+ * of signatures in the MAR file.
+ * @param hasAdditionalBlocks Optional out parameter specifying if the MAR
+ * file has additional blocks or not.
+ * @param offsetAdditionalBlocks Optional out parameter for the offset to the
+ * first additional block. Value is only valid if
+ * hasAdditionalBlocks is not equal to 0.
+ * @param numAdditionalBlocks Optional out parameter for the number of
+ * additional blocks. Value is only valid if
+ * has_additional_blocks is not equal to 0.
+ * @return 0 on success and non-zero on failure.
+ */
+int get_mar_file_info(const char *path,
+ int *hasSignatureBlock,
+ uint32_t *numSignatures,
+ int *hasAdditionalBlocks,
+ uint32_t *offsetAdditionalBlocks,
+ uint32_t *numAdditionalBlocks);
+
+/**
+ * Reads the product info block from the MAR file's additional block section.
+ * The caller is responsible for freeing the fields in infoBlock
+ * if the return is successful.
+ *
+ * @param infoBlock Out parameter for where to store the result to
+ * @return 0 on success, -1 on failure
+*/
+int
+read_product_info_block(char *path,
+ struct ProductInformationBlock *infoBlock);
+
+/**
+ * Refreshes the product information block with the new information.
+ * The input MAR must not be signed or the function call will fail.
+ *
+ * @param path The path to the MAR file whose product info block
+ * should be refreshed.
+ * @param infoBlock Out parameter for where to store the result to
+ * @return 0 on success, -1 on failure
+*/
+int
+refresh_product_info_block(const char *path,
+ struct ProductInformationBlock *infoBlock);
+
+/**
+ * Writes out a copy of the MAR at src but with the signature block stripped.
+ *
+ * @param src The path of the source MAR file
+ * @param dest The path of the MAR file to write out that
+ has no signature block
+ * @return 0 on success
+ * -1 on error
+*/
+int
+strip_signature_block(const char *src, const char * dest);
+
+/**
+ * Extracts a signature from a MAR file, base64 encodes it, and writes it out
+ *
+ * @param src The path of the source MAR file
+ * @param sigIndex The index of the signature to extract
+ * @param dest The path of file to write the signature to
+ * @return 0 on success
+ * -1 on error
+*/
+int
+extract_signature(const char *src, uint32_t sigIndex, const char * dest);
+
+/**
+ * Imports a base64 encoded signature into a MAR file
+ *
+ * @param src The path of the source MAR file
+ * @param sigIndex The index of the signature to import
+ * @param base64SigFile A file which contains the signature to import
+ * @param dest The path of the destination MAR file with replaced signature
+ * @return 0 on success
+ * -1 on error
+*/
+int
+import_signature(const char *src,
+ uint32_t sigIndex,
+ const char * base64SigFile,
+ const char *dest);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MAR_CMDLINE_H__ */
diff --git a/onlineupdate/source/update/src/mar_create.c b/onlineupdate/source/update/src/mar_create.c
new file mode 100644
index 000000000000..c2ce10126cbd
--- /dev/null
+++ b/onlineupdate/source/update/src/mar_create.c
@@ -0,0 +1,399 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mar_private.h"
+#include "mar_cmdline.h"
+#include "mar.h"
+
+#ifdef XP_WIN
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#include <unistd.h>
+#endif
+
+struct MarItemStack {
+ void *head;
+ uint32_t size_used;
+ uint32_t size_allocated;
+ uint32_t last_offset;
+};
+
+/**
+ * Push a new item onto the stack of items. The stack is a single block
+ * of memory.
+ */
+static int mar_push(struct MarItemStack *stack, uint32_t length, uint32_t flags,
+ const char *name) {
+ int namelen;
+ uint32_t n_offset, n_length, n_flags;
+ uint32_t size;
+ char *data;
+
+ namelen = strlen(name);
+ size = MAR_ITEM_SIZE(namelen);
+
+ if (stack->size_allocated - stack->size_used < size) {
+ /* increase size of stack */
+ size_t size_needed = ROUND_UP(stack->size_used + size, BLOCKSIZE);
+ stack->head = realloc(stack->head, size_needed);
+ if (!stack->head)
+ return -1;
+ stack->size_allocated = size_needed;
+ }
+
+ data = (((char *) stack->head) + stack->size_used);
+
+ n_offset = htonl(stack->last_offset);
+ n_length = htonl(length);
+ n_flags = htonl(flags);
+
+ memcpy(data, &n_offset, sizeof(n_offset));
+ data += sizeof(n_offset);
+
+ memcpy(data, &n_length, sizeof(n_length));
+ data += sizeof(n_length);
+
+ memcpy(data, &n_flags, sizeof(n_flags));
+ data += sizeof(n_flags);
+
+ memcpy(data, name, namelen + 1);
+
+ stack->size_used += size;
+ stack->last_offset += length;
+ return 0;
+}
+
+static int mar_concat_file(FILE *fp, const char *path) {
+ FILE *in;
+ char buf[BLOCKSIZE];
+ size_t len;
+ int rv = 0;
+
+ in = fopen(path, "rb");
+ if (!in) {
+ fprintf(stderr, "ERROR: could not open file in mar_concat_file()\n");
+ perror(path);
+ return -1;
+ }
+
+ while ((len = fread(buf, 1, BLOCKSIZE, in)) > 0) {
+ if (fwrite(buf, len, 1, fp) != 1) {
+ rv = -1;
+ break;
+ }
+ }
+
+ fclose(in);
+ return rv;
+}
+
+/**
+ * Writes out the product information block to the specified file.
+ *
+ * @param fp The opened MAR file being created.
+ * @param stack A pointer to the MAR item stack being used to create
+ * the MAR
+ * @param infoBlock The product info block to store in the file.
+ * @return 0 on success.
+*/
+static int
+mar_concat_product_info_block(FILE *fp,
+ struct MarItemStack *stack,
+ struct ProductInformationBlock *infoBlock)
+{
+ char buf[PIB_MAX_MAR_CHANNEL_ID_SIZE + PIB_MAX_PRODUCT_VERSION_SIZE];
+ uint32_t additionalBlockID = 1, infoBlockSize, unused;
+ if (!fp || !infoBlock ||
+ !infoBlock->MARChannelID ||
+ !infoBlock->productVersion) {
+ return -1;
+ }
+
+ /* The MAR channel name must be < 64 bytes per the spec */
+ if (strlen(infoBlock->MARChannelID) > PIB_MAX_MAR_CHANNEL_ID_SIZE) {
+ return -1;
+ }
+
+ /* The product version must be < 32 bytes per the spec */
+ if (strlen(infoBlock->productVersion) > PIB_MAX_PRODUCT_VERSION_SIZE) {
+ return -1;
+ }
+
+ /* Although we don't need the product information block size to include the
+ maximum MAR channel name and product version, we allocate the maximum
+ amount to make it easier to modify the MAR file for repurposing MAR files
+ to different MAR channels. + 2 is for the NULL terminators. */
+ infoBlockSize = sizeof(infoBlockSize) +
+ sizeof(additionalBlockID) +
+ PIB_MAX_MAR_CHANNEL_ID_SIZE +
+ PIB_MAX_PRODUCT_VERSION_SIZE + 2;
+ if (stack) {
+ stack->last_offset += infoBlockSize;
+ }
+
+ /* Write out the product info block size */
+ infoBlockSize = htonl(infoBlockSize);
+ if (fwrite(&infoBlockSize,
+ sizeof(infoBlockSize), 1, fp) != 1) {
+ return -1;
+ }
+ infoBlockSize = ntohl(infoBlockSize);
+
+ /* Write out the product info block ID */
+ additionalBlockID = htonl(additionalBlockID);
+ if (fwrite(&additionalBlockID,
+ sizeof(additionalBlockID), 1, fp) != 1) {
+ return -1;
+ }
+ additionalBlockID = ntohl(additionalBlockID);
+
+ /* Write out the channel name and NULL terminator */
+ if (fwrite(infoBlock->MARChannelID,
+ strlen(infoBlock->MARChannelID) + 1, 1, fp) != 1) {
+ return -1;
+ }
+
+ /* Write out the product version string and NULL terminator */
+ if (fwrite(infoBlock->productVersion,
+ strlen(infoBlock->productVersion) + 1, 1, fp) != 1) {
+ return -1;
+ }
+
+ /* Write out the rest of the block that is unused */
+ unused = infoBlockSize - (sizeof(infoBlockSize) +
+ sizeof(additionalBlockID) +
+ strlen(infoBlock->MARChannelID) +
+ strlen(infoBlock->productVersion) + 2);
+ memset(buf, 0, sizeof(buf));
+ if (fwrite(buf, unused, 1, fp) != 1) {
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * Refreshes the product information block with the new information.
+ * The input MAR must not be signed or the function call will fail.
+ *
+ * @param path The path to the MAR file whose product info block
+ * should be refreshed.
+ * @param infoBlock Out parameter for where to store the result to
+ * @return 0 on success, -1 on failure
+*/
+int
+refresh_product_info_block(const char *path,
+ struct ProductInformationBlock *infoBlock)
+{
+ FILE *fp ;
+ int rv;
+ uint32_t numSignatures, additionalBlockSize, additionalBlockID,
+ offsetAdditionalBlocks, numAdditionalBlocks, i;
+ int additionalBlocks, hasSignatureBlock;
+ int64_t oldPos;
+
+ rv = get_mar_file_info(path,
+ &hasSignatureBlock,
+ &numSignatures,
+ &additionalBlocks,
+ &offsetAdditionalBlocks,
+ &numAdditionalBlocks);
+ if (rv) {
+ fprintf(stderr, "ERROR: Could not obtain MAR information.\n");
+ return -1;
+ }
+
+ if (hasSignatureBlock && numSignatures) {
+ fprintf(stderr, "ERROR: Cannot refresh a signed MAR\n");
+ return -1;
+ }
+
+ fp = fopen(path, "r+b");
+ if (!fp) {
+ fprintf(stderr, "ERROR: could not open target file: %s\n", path);
+ return -1;
+ }
+
+ if (fseeko(fp, offsetAdditionalBlocks, SEEK_SET)) {
+ fprintf(stderr, "ERROR: could not seek to additional blocks\n");
+ fclose(fp);
+ return -1;
+ }
+
+ for (i = 0; i < numAdditionalBlocks; ++i) {
+ /* Get the position of the start of this block */
+ oldPos = ftello(fp);
+
+ /* Read the additional block size */
+ if (fread(&additionalBlockSize,
+ sizeof(additionalBlockSize),
+ 1, fp) != 1) {
+ fclose(fp);
+ return -1;
+ }
+ additionalBlockSize = ntohl(additionalBlockSize);
+
+ /* Read the additional block ID */
+ if (fread(&additionalBlockID,
+ sizeof(additionalBlockID),
+ 1, fp) != 1) {
+ fclose(fp);
+ return -1;
+ }
+ additionalBlockID = ntohl(additionalBlockID);
+
+ if (PRODUCT_INFO_BLOCK_ID == additionalBlockID) {
+ if (fseeko(fp, oldPos, SEEK_SET)) {
+ fprintf(stderr, "Could not seek back to Product Information Block\n");
+ fclose(fp);
+ return -1;
+ }
+
+ if (mar_concat_product_info_block(fp, NULL, infoBlock)) {
+ fprintf(stderr, "Could not concat Product Information Block\n");
+ fclose(fp);
+ return -1;
+ }
+
+ fclose(fp);
+ return 0;
+ } else {
+ /* This is not the additional block you're looking for. Move along. */
+ if (fseek(fp, additionalBlockSize, SEEK_CUR)) {
+ fprintf(stderr, "ERROR: Could not seek past current block.\n");
+ fclose(fp);
+ return -1;
+ }
+ }
+ }
+
+ /* If we had a product info block we would have already returned */
+ fclose(fp);
+ fprintf(stderr, "ERROR: Could not refresh because block does not exist\n");
+ return -1;
+}
+
+/**
+ * Create a MAR file from a set of files.
+ * @param dest The path to the file to create. This path must be
+ * compatible with fopen.
+ * @param numfiles The number of files to store in the archive.
+ * @param files The list of null-terminated file paths. Each file
+ * path must be compatible with fopen.
+ * @param infoBlock The information to store in the product information block.
+ * @return A non-zero value if an error occurs.
+ */
+int mar_create(const char *dest, int
+ num_files, char **files,
+ struct ProductInformationBlock *infoBlock) {
+ struct MarItemStack stack;
+ uint32_t offset_to_index = 0, size_of_index,
+ numSignatures, numAdditionalSections;
+ uint64_t sizeOfEntireMAR = 0;
+ struct stat st;
+ FILE *fp;
+ int i, rv = -1;
+
+ memset(&stack, 0, sizeof(stack));
+
+ fp = fopen(dest, "wb");
+ if (!fp) {
+ fprintf(stderr, "ERROR: could not create target file: %s\n", dest);
+ return -1;
+ }
+
+ if (fwrite(MAR_ID, MAR_ID_SIZE, 1, fp) != 1)
+ goto failure;
+ if (fwrite(&offset_to_index, sizeof(uint32_t), 1, fp) != 1)
+ goto failure;
+
+ stack.last_offset = MAR_ID_SIZE +
+ sizeof(offset_to_index) +
+ sizeof(numSignatures) +
+ sizeof(numAdditionalSections) +
+ sizeof(sizeOfEntireMAR);
+
+ /* We will circle back on this at the end of the MAR creation to fill it */
+ if (fwrite(&sizeOfEntireMAR, sizeof(sizeOfEntireMAR), 1, fp) != 1) {
+ goto failure;
+ }
+
+ /* Write out the number of signatures, for now only at most 1 is supported */
+ numSignatures = 0;
+ if (fwrite(&numSignatures, sizeof(numSignatures), 1, fp) != 1) {
+ goto failure;
+ }
+
+ /* Write out the number of additional sections, for now just 1
+ for the product info block */
+ numAdditionalSections = htonl(1);
+ if (fwrite(&numAdditionalSections,
+ sizeof(numAdditionalSections), 1, fp) != 1) {
+ goto failure;
+ }
+ numAdditionalSections = ntohl(numAdditionalSections);
+
+ if (mar_concat_product_info_block(fp, &stack, infoBlock)) {
+ goto failure;
+ }
+
+ for (i = 0; i < num_files; ++i) {
+ if (stat(files[i], &st)) {
+ fprintf(stderr, "ERROR: file not found: %s\n", files[i]);
+ goto failure;
+ }
+
+ if (mar_push(&stack, st.st_size, st.st_mode & 0777, files[i]))
+ goto failure;
+
+ /* concatenate input file to archive */
+ if (mar_concat_file(fp, files[i]))
+ goto failure;
+ }
+
+ /* write out the index (prefixed with length of index) */
+ size_of_index = htonl(stack.size_used);
+ if (fwrite(&size_of_index, sizeof(size_of_index), 1, fp) != 1)
+ goto failure;
+ if (fwrite(stack.head, stack.size_used, 1, fp) != 1)
+ goto failure;
+
+ /* To protect against invalid MAR files, we assumes that the MAR file
+ size is less than or equal to MAX_SIZE_OF_MAR_FILE. */
+ if (ftell(fp) > MAX_SIZE_OF_MAR_FILE) {
+ goto failure;
+ }
+
+ /* write out offset to index file in network byte order */
+ offset_to_index = htonl(stack.last_offset);
+ if (fseek(fp, MAR_ID_SIZE, SEEK_SET))
+ goto failure;
+ if (fwrite(&offset_to_index, sizeof(offset_to_index), 1, fp) != 1)
+ goto failure;
+ offset_to_index = ntohl(stack.last_offset);
+
+ sizeOfEntireMAR = ((uint64_t)stack.last_offset) +
+ stack.size_used +
+ sizeof(size_of_index);
+ sizeOfEntireMAR = HOST_TO_NETWORK64(sizeOfEntireMAR);
+ if (fwrite(&sizeOfEntireMAR, sizeof(sizeOfEntireMAR), 1, fp) != 1)
+ goto failure;
+ sizeOfEntireMAR = NETWORK_TO_HOST64(sizeOfEntireMAR);
+
+ rv = 0;
+failure:
+ if (stack.head)
+ free(stack.head);
+ fclose(fp);
+ if (rv)
+ remove(dest);
+ return rv;
+}
diff --git a/onlineupdate/source/update/src/mar_extract.c b/onlineupdate/source/update/src/mar_extract.c
new file mode 100644
index 000000000000..ec1cd6c53446
--- /dev/null
+++ b/onlineupdate/source/update/src/mar_extract.c
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include "mar_private.h"
+#include "mar.h"
+
+#ifdef XP_WIN
+#include <io.h>
+#include <direct.h>
+#endif
+
+/* Ensure that the directory containing this file exists */
+static int mar_ensure_parent_dir(const char *path)
+{
+ char *slash = strrchr(path, '/');
+ if (slash)
+ {
+ *slash = '\0';
+ mar_ensure_parent_dir(path);
+#ifdef XP_WIN
+ _mkdir(path);
+#else
+ mkdir(path, 0755);
+#endif
+ *slash = '/';
+ }
+ return 0;
+}
+
+static int mar_test_callback(MarFile *mar, const MarItem *item, void *unused) {
+ FILE *fp;
+ char buf[BLOCKSIZE];
+ int fd, len, offset = 0;
+
+ if (mar_ensure_parent_dir(item->name))
+ return -1;
+
+#ifdef XP_WIN
+ fd = _open(item->name, _O_BINARY|_O_CREAT|_O_TRUNC|_O_WRONLY, item->flags);
+#else
+ fd = creat(item->name, item->flags);
+#endif
+ if (fd == -1) {
+ fprintf(stderr, "ERROR: could not create file in mar_test_callback()\n");
+ perror(item->name);
+ return -1;
+ }
+
+ fp = fdopen(fd, "wb");
+ if (!fp)
+ return -1;
+
+ while ((len = mar_read(mar, item, offset, buf, sizeof(buf))) > 0) {
+ if (fwrite(buf, len, 1, fp) != 1)
+ break;
+ offset += len;
+ }
+
+ fclose(fp);
+ return len == 0 ? 0 : -1;
+}
+
+int mar_extract(const char *path) {
+ MarFile *mar;
+ int rv;
+
+ mar = mar_open(path);
+ if (!mar)
+ return -1;
+
+ rv = mar_enum_items(mar, mar_test_callback, NULL);
+
+ mar_close(mar);
+ return rv;
+}
diff --git a/onlineupdate/source/update/src/mar_private.h b/onlineupdate/source/update/src/mar_private.h
new file mode 100644
index 000000000000..8a7fb45ccd82
--- /dev/null
+++ b/onlineupdate/source/update/src/mar_private.h
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MAR_PRIVATE_H__
+#define MAR_PRIVATE_H__
+
+#include "limits.h"
+#include "mozilla/Assertions.h"
+#include <stdint.h>
+
+#define BLOCKSIZE 4096
+#define ROUND_UP(n, incr) (((n) / (incr) + 1) * (incr))
+
+#define MAR_ID "MAR1"
+#define MAR_ID_SIZE 4
+
+/* The signature block comes directly after the header block
+ which is 16 bytes */
+#define SIGNATURE_BLOCK_OFFSET 16
+
+/* Make sure the file is less than 500MB. We do this to protect against
+ invalid MAR files. */
+#define MAX_SIZE_OF_MAR_FILE ((int64_t)524288000)
+
+/* Existing code makes assumptions that the file size is
+ smaller than LONG_MAX. */
+MOZ_STATIC_ASSERT(MAX_SIZE_OF_MAR_FILE < ((int64_t)LONG_MAX),
+ "max mar file size is too big");
+
+/* We store at most the size up to the signature block + 4
+ bytes per BLOCKSIZE bytes */
+MOZ_STATIC_ASSERT(sizeof(BLOCKSIZE) < \
+ (SIGNATURE_BLOCK_OFFSET + sizeof(uint32_t)),
+ "BLOCKSIZE is too big");
+
+/* The maximum size of any signature supported by current and future
+ implementations of the signmar program. */
+#define MAX_SIGNATURE_LENGTH 2048
+
+/* Each additional block has a unique ID.
+ The product information block has an ID of 1. */
+#define PRODUCT_INFO_BLOCK_ID 1
+
+#define MAR_ITEM_SIZE(namelen) (3*sizeof(uint32_t) + (namelen) + 1)
+
+/* Product Information Block (PIB) constants */
+#define PIB_MAX_MAR_CHANNEL_ID_SIZE 63
+#define PIB_MAX_PRODUCT_VERSION_SIZE 31
+
+/* The mar program is compiled as a host bin so we don't have access to NSPR at
+ runtime. For that reason we use ntohl, htonl, and define HOST_TO_NETWORK64
+ instead of the NSPR equivalents. */
+#ifdef XP_WIN
+#include <winsock2.h>
+#define ftello _ftelli64
+#define fseeko _fseeki64
+#else
+#define _FILE_OFFSET_BITS 64
+#include <netinet/in.h>
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+
+#define HOST_TO_NETWORK64(x) ( \
+ ((((uint64_t) x) & 0xFF) << 56) | \
+ ((((uint64_t) x) >> 8) & 0xFF) << 48) | \
+ (((((uint64_t) x) >> 16) & 0xFF) << 40) | \
+ (((((uint64_t) x) >> 24) & 0xFF) << 32) | \
+ (((((uint64_t) x) >> 32) & 0xFF) << 24) | \
+ (((((uint64_t) x) >> 40) & 0xFF) << 16) | \
+ (((((uint64_t) x) >> 48) & 0xFF) << 8) | \
+ (((uint64_t) x) >> 56)
+#define NETWORK_TO_HOST64 HOST_TO_NETWORK64
+
+#endif /* MAR_PRIVATE_H__ */
diff --git a/onlineupdate/source/update/src/mar_read.c b/onlineupdate/source/update/src/mar_read.c
new file mode 100644
index 000000000000..7be225385403
--- /dev/null
+++ b/onlineupdate/source/update/src/mar_read.c
@@ -0,0 +1,570 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mar_private.h"
+#include "mar.h"
+
+#ifdef XP_WIN
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#endif
+
+
+/* this is the same hash algorithm used by nsZipArchive.cpp */
+static uint32_t mar_hash_name(const char *name) {
+ uint32_t val = 0;
+ unsigned char* c;
+
+ for (c = (unsigned char *) name; *c; ++c)
+ val = val*37 + *c;
+
+ return val % TABLESIZE;
+}
+
+static int mar_insert_item(MarFile *mar, const char *name, int namelen,
+ uint32_t offset, uint32_t length, uint32_t flags) {
+ MarItem *item, *root;
+ uint32_t hash;
+
+ item = (MarItem *) malloc(sizeof(MarItem) + namelen);
+ if (!item)
+ return -1;
+ item->next = NULL;
+ item->offset = offset;
+ item->length = length;
+ item->flags = flags;
+ memcpy(item->name, name, namelen + 1);
+
+ hash = mar_hash_name(name);
+
+ root = mar->item_table[hash];
+ if (!root) {
+ mar->item_table[hash] = item;
+ } else {
+ /* append item */
+ while (root->next)
+ root = root->next;
+ root->next = item;
+ }
+ return 0;
+}
+
+static int mar_consume_index(MarFile *mar, char **buf, const char *buf_end) {
+ /*
+ * Each item has the following structure:
+ * uint32_t offset (network byte order)
+ * uint32_t length (network byte order)
+ * uint32_t flags (network byte order)
+ * char name[N] (where N >= 1)
+ * char null_byte;
+ */
+ uint32_t offset;
+ uint32_t length;
+ uint32_t flags;
+ const char *name;
+ int namelen;
+
+ if ((buf_end - *buf) < (int)(3*sizeof(uint32_t) + 2))
+ return -1;
+
+ memcpy(&offset, *buf, sizeof(offset));
+ *buf += sizeof(offset);
+
+ memcpy(&length, *buf, sizeof(length));
+ *buf += sizeof(length);
+
+ memcpy(&flags, *buf, sizeof(flags));
+ *buf += sizeof(flags);
+
+ offset = ntohl(offset);
+ length = ntohl(length);
+ flags = ntohl(flags);
+
+ name = *buf;
+ /* find namelen; must take care not to read beyond buf_end */
+ while (**buf) {
+ if (*buf == buf_end)
+ return -1;
+ ++(*buf);
+ }
+ namelen = (*buf - name);
+ /* consume null byte */
+ if (*buf == buf_end)
+ return -1;
+ ++(*buf);
+
+ return mar_insert_item(mar, name, namelen, offset, length, flags);
+}
+
+static int mar_read_index(MarFile *mar) {
+ char id[MAR_ID_SIZE], *buf, *bufptr, *bufend;
+ uint32_t offset_to_index, size_of_index;
+
+ /* verify MAR ID */
+ if (fread(id, MAR_ID_SIZE, 1, mar->fp) != 1)
+ return -1;
+ if (memcmp(id, MAR_ID, MAR_ID_SIZE) != 0)
+ return -1;
+
+ if (fread(&offset_to_index, sizeof(uint32_t), 1, mar->fp) != 1)
+ return -1;
+ offset_to_index = ntohl(offset_to_index);
+
+ if (fseek(mar->fp, offset_to_index, SEEK_SET))
+ return -1;
+ if (fread(&size_of_index, sizeof(uint32_t), 1, mar->fp) != 1)
+ return -1;
+ size_of_index = ntohl(size_of_index);
+
+ buf = (char *) malloc(size_of_index);
+ if (!buf)
+ return -1;
+ if (fread(buf, size_of_index, 1, mar->fp) != 1) {
+ free(buf);
+ return -1;
+ }
+
+ bufptr = buf;
+ bufend = buf + size_of_index;
+ while (bufptr < bufend && mar_consume_index(mar, &bufptr, bufend) == 0);
+
+ free(buf);
+ return (bufptr == bufend) ? 0 : -1;
+}
+
+/**
+ * Internal shared code for mar_open and mar_wopen.
+ * On failure, will fclose(fp).
+ */
+static MarFile *mar_fpopen(FILE *fp)
+{
+ MarFile *mar;
+
+ mar = (MarFile *) malloc(sizeof(*mar));
+ if (!mar) {
+ fclose(fp);
+ return NULL;
+ }
+
+ mar->fp = fp;
+ memset(mar->item_table, 0, sizeof(mar->item_table));
+ if (mar_read_index(mar)) {
+ mar_close(mar);
+ return NULL;
+ }
+
+ return mar;
+}
+
+MarFile *mar_open(const char *path) {
+ FILE *fp;
+
+ fp = fopen(path, "rb");
+ if (!fp) {
+ fprintf(stderr, "ERROR: could not open file in mar_open()\n");
+ perror(path);
+ return NULL;
+ }
+
+ return mar_fpopen(fp);
+}
+
+#ifdef XP_WIN
+MarFile *mar_wopen(const wchar_t *path) {
+ FILE *fp;
+
+ _wfopen_s(&fp, path, L"rb");
+ if (!fp) {
+ fprintf(stderr, "ERROR: could not open file in mar_wopen()\n");
+ _wperror(path);
+ return NULL;
+ }
+
+ return mar_fpopen(fp);
+}
+#endif
+
+void mar_close(MarFile *mar) {
+ MarItem *item;
+ int i;
+
+ fclose(mar->fp);
+
+ for (i = 0; i < TABLESIZE; ++i) {
+ item = mar->item_table[i];
+ while (item) {
+ MarItem *temp = item;
+ item = item->next;
+ free(temp);
+ }
+ }
+
+ free(mar);
+}
+
+/**
+ * Determines the MAR file information.
+ *
+ * @param fp An opened MAR file in read mode.
+ * @param hasSignatureBlock Optional out parameter specifying if the MAR
+ * file has a signature block or not.
+ * @param numSignatures Optional out parameter for storing the number
+ * of signatures in the MAR file.
+ * @param hasAdditionalBlocks Optional out parameter specifying if the MAR
+ * file has additional blocks or not.
+ * @param offsetAdditionalBlocks Optional out parameter for the offset to the
+ * first additional block. Value is only valid if
+ * hasAdditionalBlocks is not equal to 0.
+ * @param numAdditionalBlocks Optional out parameter for the number of
+ * additional blocks. Value is only valid if
+ * hasAdditionalBlocks is not equal to 0.
+ * @return 0 on success and non-zero on failure.
+ */
+int get_mar_file_info_fp(FILE *fp,
+ int *hasSignatureBlock,
+ uint32_t *numSignatures,
+ int *hasAdditionalBlocks,
+ uint32_t *offsetAdditionalBlocks,
+ uint32_t *numAdditionalBlocks)
+{
+ uint32_t offsetToIndex, offsetToContent, signatureCount, signatureLen, i;
+
+ /* One of hasSignatureBlock or hasAdditionalBlocks must be non NULL */
+ if (!hasSignatureBlock && !hasAdditionalBlocks) {
+ return -1;
+ }
+
+
+ /* Skip to the start of the offset index */
+ if (fseek(fp, MAR_ID_SIZE, SEEK_SET)) {
+ return -1;
+ }
+
+ /* Read the offset to the index. */
+ if (fread(&offsetToIndex, sizeof(offsetToIndex), 1, fp) != 1) {
+ return -1;
+ }
+ offsetToIndex = ntohl(offsetToIndex);
+
+ if (numSignatures) {
+ /* Skip past the MAR file size field */
+ if (fseek(fp, sizeof(uint64_t), SEEK_CUR)) {
+ return -1;
+ }
+
+ /* Read the number of signatures field */
+ if (fread(numSignatures, sizeof(*numSignatures), 1, fp) != 1) {
+ return -1;
+ }
+ *numSignatures = ntohl(*numSignatures);
+ }
+
+ /* Skip to the first index entry past the index size field
+ We do it in 2 calls because offsetToIndex + sizeof(uint32_t)
+ could oerflow in theory. */
+ if (fseek(fp, offsetToIndex, SEEK_SET)) {
+ return -1;
+ }
+
+ if (fseek(fp, sizeof(uint32_t), SEEK_CUR)) {
+ return -1;
+ }
+
+ /* Read the first offset to content field. */
+ if (fread(&offsetToContent, sizeof(offsetToContent), 1, fp) != 1) {
+ return -1;
+ }
+ offsetToContent = ntohl(offsetToContent);
+
+ /* Check if we have a new or old MAR file */
+ if (hasSignatureBlock) {
+ if (offsetToContent == MAR_ID_SIZE + sizeof(uint32_t)) {
+ *hasSignatureBlock = 0;
+ } else {
+ *hasSignatureBlock = 1;
+ }
+ }
+
+ /* If the caller doesn't care about the product info block
+ value, then just return */
+ if (!hasAdditionalBlocks) {
+ return 0;
+ }
+
+ /* Skip to the start of the signature block */
+ if (fseeko(fp, SIGNATURE_BLOCK_OFFSET, SEEK_SET)) {
+ return -1;
+ }
+
+ /* Get the number of signatures */
+ if (fread(&signatureCount, sizeof(signatureCount), 1, fp) != 1) {
+ return -1;
+ }
+ signatureCount = ntohl(signatureCount);
+
+ /* Check that we have less than the max amount of signatures so we don't
+ waste too much of either updater's or signmar's time. */
+ if (signatureCount > MAX_SIGNATURES) {
+ return -1;
+ }
+
+ /* Skip past the whole signature block */
+ for (i = 0; i < signatureCount; i++) {
+ /* Skip past the signature algorithm ID */
+ if (fseek(fp, sizeof(uint32_t), SEEK_CUR)) {
+ return -1;
+ }
+
+ /* Read the signature length and skip past the signature */
+ if (fread(&signatureLen, sizeof(uint32_t), 1, fp) != 1) {
+ return -1;
+ }
+ signatureLen = ntohl(signatureLen);
+ if (fseek(fp, signatureLen, SEEK_CUR)) {
+ return -1;
+ }
+ }
+
+ if (ftell(fp) == offsetToContent) {
+ *hasAdditionalBlocks = 0;
+ } else {
+ if (numAdditionalBlocks) {
+ /* We have an additional block, so read in the number of additional blocks
+ and set the offset. */
+ *hasAdditionalBlocks = 1;
+ if (fread(numAdditionalBlocks, sizeof(uint32_t), 1, fp) != 1) {
+ return -1;
+ }
+ *numAdditionalBlocks = ntohl(*numAdditionalBlocks);
+ if (offsetAdditionalBlocks) {
+ *offsetAdditionalBlocks = ftell(fp);
+ }
+ } else if (offsetAdditionalBlocks) {
+ /* numAdditionalBlocks is not specified but offsetAdditionalBlocks
+ is, so fill it! */
+ *offsetAdditionalBlocks = ftell(fp) + sizeof(uint32_t);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Reads the product info block from the MAR file's additional block section.
+ * The caller is responsible for freeing the fields in infoBlock
+ * if the return is successful.
+ *
+ * @param infoBlock Out parameter for where to store the result to
+ * @return 0 on success, -1 on failure
+*/
+int
+read_product_info_block(char *path,
+ struct ProductInformationBlock *infoBlock)
+{
+ int rv;
+ MarFile mar;
+ mar.fp = fopen(path, "rb");
+ if (!mar.fp) {
+ fprintf(stderr, "ERROR: could not open file in read_product_info_block()\n");
+ perror(path);
+ return -1;
+ }
+ rv = mar_read_product_info_block(&mar, infoBlock);
+ fclose(mar.fp);
+ return rv;
+}
+
+/**
+ * Reads the product info block from the MAR file's additional block section.
+ * The caller is responsible for freeing the fields in infoBlock
+ * if the return is successful.
+ *
+ * @param infoBlock Out parameter for where to store the result to
+ * @return 0 on success, -1 on failure
+*/
+int
+mar_read_product_info_block(MarFile *mar,
+ struct ProductInformationBlock *infoBlock)
+{
+ uint32_t i, offsetAdditionalBlocks, numAdditionalBlocks,
+ additionalBlockSize, additionalBlockID;
+ int hasAdditionalBlocks;
+
+ /* The buffer size is 97 bytes because the MAR channel name < 64 bytes, and
+ product version < 32 bytes + 3 NULL terminator bytes. */
+ char buf[97] = { '\0' };
+ int ret = get_mar_file_info_fp(mar->fp, NULL, NULL,
+ &hasAdditionalBlocks,
+ &offsetAdditionalBlocks,
+ &numAdditionalBlocks);
+ for (i = 0; i < numAdditionalBlocks; ++i) {
+ /* Read the additional block size */
+ if (fread(&additionalBlockSize,
+ sizeof(additionalBlockSize),
+ 1, mar->fp) != 1) {
+ return -1;
+ }
+ additionalBlockSize = ntohl(additionalBlockSize) -
+ sizeof(additionalBlockSize) -
+ sizeof(additionalBlockID);
+
+ /* Read the additional block ID */
+ if (fread(&additionalBlockID,
+ sizeof(additionalBlockID),
+ 1, mar->fp) != 1) {
+ return -1;
+ }
+ additionalBlockID = ntohl(additionalBlockID);
+
+ if (PRODUCT_INFO_BLOCK_ID == additionalBlockID) {
+ const char *location;
+ int len;
+
+ /* This block must be at most 104 bytes.
+ MAR channel name < 64 bytes, and product version < 32 bytes + 3 NULL
+ terminator bytes. We only check for 96 though because we remove 8
+ bytes above from the additionalBlockSize: We subtract
+ sizeof(additionalBlockSize) and sizeof(additionalBlockID) */
+ if (additionalBlockSize > 96) {
+ return -1;
+ }
+
+ if (fread(buf, additionalBlockSize, 1, mar->fp) != 1) {
+ return -1;
+ }
+
+ /* Extract the MAR channel name from the buffer. For now we
+ point to the stack allocated buffer but we strdup this
+ if we are within bounds of each field's max length. */
+ location = buf;
+ len = strlen(location);
+ infoBlock->MARChannelID = location;
+ location += len + 1;
+ if (len >= 64) {
+ infoBlock->MARChannelID = NULL;
+ return -1;
+ }
+
+ /* Extract the version from the buffer */
+ len = strlen(location);
+ infoBlock->productVersion = location;
+ location += len + 1;
+ if (len >= 32) {
+ infoBlock->MARChannelID = NULL;
+ infoBlock->productVersion = NULL;
+ return -1;
+ }
+ infoBlock->MARChannelID =
+ strdup(infoBlock->MARChannelID);
+ infoBlock->productVersion =
+ strdup(infoBlock->productVersion);
+ return 0;
+ } else {
+ /* This is not the additional block you're looking for. Move along. */
+ if (fseek(mar->fp, additionalBlockSize, SEEK_CUR)) {
+ return -1;
+ }
+ }
+ }
+
+ /* If we had a product info block we would have already returned */
+ return -1;
+}
+
+const MarItem *mar_find_item(MarFile *mar, const char *name) {
+ uint32_t hash;
+ const MarItem *item;
+
+ hash = mar_hash_name(name);
+
+ item = mar->item_table[hash];
+ while (item && strcmp(item->name, name) != 0)
+ item = item->next;
+
+ return item;
+}
+
+int mar_enum_items(MarFile *mar, MarItemCallback callback, void *closure) {
+ MarItem *item;
+ int i;
+
+ for (i = 0; i < TABLESIZE; ++i) {
+ item = mar->item_table[i];
+ while (item) {
+ int rv = callback(mar, item, closure);
+ if (rv)
+ return rv;
+ item = item->next;
+ }
+ }
+
+ return 0;
+}
+
+int mar_read(MarFile *mar, const MarItem *item, int offset, char *buf,
+ int bufsize) {
+ int nr;
+
+ if (offset == (int) item->length)
+ return 0;
+ if (offset > (int) item->length)
+ return -1;
+
+ nr = item->length - offset;
+ if (nr > bufsize)
+ nr = bufsize;
+
+ if (fseek(mar->fp, item->offset + offset, SEEK_SET))
+ return -1;
+
+ return fread(buf, 1, nr, mar->fp);
+}
+
+/**
+ * Determines the MAR file information.
+ *
+ * @param path The path of the MAR file to check.
+ * @param hasSignatureBlock Optional out parameter specifying if the MAR
+ * file has a signature block or not.
+ * @param numSignatures Optional out parameter for storing the number
+ * of signatures in the MAR file.
+ * @param hasAdditionalBlocks Optional out parameter specifying if the MAR
+ * file has additional blocks or not.
+ * @param offsetAdditionalBlocks Optional out parameter for the offset to the
+ * first additional block. Value is only valid if
+ * hasAdditionalBlocks is not equal to 0.
+ * @param numAdditionalBlocks Optional out parameter for the number of
+ * additional blocks. Value is only valid if
+ * has_additional_blocks is not equal to 0.
+ * @return 0 on success and non-zero on failure.
+ */
+int get_mar_file_info(const char *path,
+ int *hasSignatureBlock,
+ uint32_t *numSignatures,
+ int *hasAdditionalBlocks,
+ uint32_t *offsetAdditionalBlocks,
+ uint32_t *numAdditionalBlocks)
+{
+ int rv;
+ FILE *fp = fopen(path, "rb");
+ if (!fp) {
+ fprintf(stderr, "ERROR: could not open file in get_mar_file_info()\n");
+ perror(path);
+ return -1;
+ }
+
+ rv = get_mar_file_info_fp(fp, hasSignatureBlock,
+ numSignatures, hasAdditionalBlocks,
+ offsetAdditionalBlocks, numAdditionalBlocks);
+
+ fclose(fp);
+ return rv;
+}
diff --git a/onlineupdate/source/update/src/moz.build b/onlineupdate/source/update/src/moz.build
new file mode 100644
index 000000000000..2d25e0849af1
--- /dev/null
+++ b/onlineupdate/source/update/src/moz.build
@@ -0,0 +1,30 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+EXPORTS += [
+ 'mar.h',
+ 'mar_cmdline.h',
+]
+
+HOST_SOURCES += [
+ 'mar_create.c',
+ 'mar_extract.c',
+ 'mar_read.c',
+]
+HostLibrary('hostmar')
+
+Library('mar')
+
+UNIFIED_SOURCES += [
+ 'mar_create.c',
+ 'mar_extract.c',
+ 'mar_read.c',
+]
+
+FORCE_STATIC_LIB = True
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+ USE_STATIC_LIBS = True
diff --git a/onlineupdate/source/update/updater/archivereader.cpp b/onlineupdate/source/update/updater/archivereader.cxx
index 6aa1f49fde9d..0bdb99220334 100644
--- a/onlineupdate/source/update/updater/archivereader.cpp
+++ b/onlineupdate/source/update/updater/archivereader.cxx
@@ -10,7 +10,7 @@
#include "bzlib.h"
#include "archivereader.h"
#include "errors.h"
-#ifdef XP_WIN
+#ifdef WNT
#include "nsAlgorithm.h" // Needed by nsVersionComparator.cpp
#include "updatehelper.h"
#endif
@@ -27,12 +27,12 @@
#endif
#define UPDATER_NO_STRING_GLUE_STL
-#include "nsVersionComparator.cpp"
+#include "nsVersionComparator.h"
#undef UPDATER_NO_STRING_GLUE_STL
-#if defined(XP_UNIX)
+#if defined(UNIX)
# include <sys/types.h>
-#elif defined(XP_WIN)
+#elif defined(WNT)
# include <io.h>
#endif
@@ -203,7 +203,7 @@ ArchiveReader::Open(const NS_tchar *path)
}
}
-#ifdef XP_WIN
+#ifdef WNT
mArchive = mar_wopen(path);
#else
mArchive = mar_open(path);
@@ -240,7 +240,7 @@ ArchiveReader::ExtractFile(const char *name, const NS_tchar *dest)
if (!item)
return READ_ERROR;
-#ifdef XP_WIN
+#ifdef WNT
FILE* fp = _wfopen(dest, L"wb+");
#else
int fd = creat(dest, item->flags);
diff --git a/onlineupdate/source/update/updater/archivereader.h b/onlineupdate/source/update/updater/archivereader.h
index 6dccd8983eb5..5fa9523eba40 100644
--- a/onlineupdate/source/update/updater/archivereader.h
+++ b/onlineupdate/source/update/updater/archivereader.h
@@ -10,7 +10,7 @@
#include <stdio.h>
#include "mar.h"
-#ifdef XP_WIN
+#ifdef WNT
typedef WCHAR NS_tchar;
#else
typedef char NS_tchar;
diff --git a/onlineupdate/source/update/updater/automounter_gonk.cpp b/onlineupdate/source/update/updater/automounter_gonk.cxx
index 3dff2a1337a1..3dff2a1337a1 100644
--- a/onlineupdate/source/update/updater/automounter_gonk.cpp
+++ b/onlineupdate/source/update/updater/automounter_gonk.cxx
diff --git a/onlineupdate/source/update/updater/bspatch.cpp b/onlineupdate/source/update/updater/bspatch.cxx
index e4b5706ef2de..8f8e0420000a 100644
--- a/onlineupdate/source/update/updater/bspatch.cpp
+++ b/onlineupdate/source/update/updater/bspatch.cxx
@@ -39,13 +39,13 @@
#include <string.h>
#include <limits.h>
-#if defined(XP_WIN)
+#if defined(WNT)
# include <io.h>
#else
# include <unistd.h>
#endif
-#ifdef XP_WIN
+#ifdef WNT
# include <winsock2.h>
#else
# include <arpa/inet.h>
diff --git a/onlineupdate/source/update/updater/loaddlls.cpp b/onlineupdate/source/update/updater/loaddlls.cxx
index b4291a5df6bf..b910723953f8 100644
--- a/onlineupdate/source/update/updater/loaddlls.cpp
+++ b/onlineupdate/source/update/updater/loaddlls.cxx
@@ -3,6 +3,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifdef WNT
#include <windows.h>
// Delayed load libraries are loaded when the first symbol is used.
@@ -101,3 +103,4 @@ struct AutoLoadSystemDependencies
}
}
} loadDLLs;
+#endif
diff --git a/onlineupdate/source/update/updater/progressui_gonk.cpp b/onlineupdate/source/update/updater/progressui-unused/progressui_gonk.cxx
index f77d0af6338a..f77d0af6338a 100644
--- a/onlineupdate/source/update/updater/progressui_gonk.cpp
+++ b/onlineupdate/source/update/updater/progressui-unused/progressui_gonk.cxx
diff --git a/onlineupdate/source/update/updater/progressui_osx.mm b/onlineupdate/source/update/updater/progressui-unused/progressui_osx.mm
index 8e3ce01eb836..8e3ce01eb836 100644
--- a/onlineupdate/source/update/updater/progressui_osx.mm
+++ b/onlineupdate/source/update/updater/progressui-unused/progressui_osx.mm
diff --git a/onlineupdate/source/update/updater/progressui.h b/onlineupdate/source/update/updater/progressui.h
index 6dc20e06bcc7..55d0d9ebf0c3 100644
--- a/onlineupdate/source/update/updater/progressui.h
+++ b/onlineupdate/source/update/updater/progressui.h
@@ -9,7 +9,7 @@
#include "updatedefines.h"
-#if defined(XP_WIN)
+#if defined(WNT)
typedef WCHAR NS_tchar;
#define NS_main wmain
#else
@@ -20,7 +20,7 @@
// Called to perform any initialization of the widget toolkit
int InitProgressUI(int *argc, NS_tchar ***argv);
-#if defined(XP_WIN)
+#if defined(WNT)
// Called on the main thread at startup
int ShowProgressUI(bool indeterminate = false, bool initUIStrings = true);
int InitProgressUIStrings();
diff --git a/onlineupdate/source/update/updater/progressui_gtk.cpp b/onlineupdate/source/update/updater/progressui_gtk.cxx
index f3c537047f25..362b3ba5ba19 100644
--- a/onlineupdate/source/update/updater/progressui_gtk.cpp
+++ b/onlineupdate/source/update/updater/progressui_gtk.cxx
@@ -4,6 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#if defined(UNIX) || defined(MACOSX)
#include <stdio.h>
#include <gtk/gtk.h>
#include <unistd.h>
@@ -129,3 +130,4 @@ UpdateProgressUI(float progress)
{
sProgressVal = progress; // 32-bit writes are atomic
}
+#endif // defined(UNIX) || defined(MACOSX)
diff --git a/onlineupdate/source/update/updater/progressui_null.cpp b/onlineupdate/source/update/updater/progressui_null.cxx
index cb3ac6369593..7c3019e0f010 100644
--- a/onlineupdate/source/update/updater/progressui_null.cpp
+++ b/onlineupdate/source/update/updater/progressui_null.cxx
@@ -4,6 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#if !defined(MACOSX) && !defined(UNIX) && !defined(WNT)
#include "progressui.h"
int InitProgressUI(int *argc, char ***argv)
@@ -23,3 +24,4 @@ void QuitProgressUI()
void UpdateProgressUI(float progress)
{
}
+#endif // !defined(MACOSX) && !defined(UNIX) && !defined(WNT)
diff --git a/onlineupdate/source/update/updater/progressui_win.cpp b/onlineupdate/source/update/updater/progressui_win.cxx
index 66232902a4e8..d0b268edaa26 100644
--- a/onlineupdate/source/update/updater/progressui_win.cpp
+++ b/onlineupdate/source/update/updater/progressui_win.cxx
@@ -4,6 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifdef WNT
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>
@@ -317,3 +318,4 @@ UpdateProgressUI(float progress)
{
sProgress = progress; // 32-bit writes are atomic
}
+#endif // WNT
diff --git a/onlineupdate/source/update/updater/updater.cpp b/onlineupdate/source/update/updater/updater.cxx
index 62237ade7bd1..8de9cc1e0898 100644
--- a/onlineupdate/source/update/updater/updater.cpp
+++ b/onlineupdate/source/update/updater/updater.cxx
@@ -66,7 +66,7 @@
// Amount of time in ms to wait for the parent process to close
#define PARENT_WAIT 5000
-#if defined(XP_MACOSX)
+#if defined(MACOSX)
// These functions are defined in launchchild_osx.mm
void LaunchChild(int argc, char **argv);
void LaunchMacPostProcess(const char* aAppBundle);
@@ -86,7 +86,7 @@ void LaunchMacPostProcess(const char* aAppBundle);
// We want to use execv to invoke the callback executable on platforms where
// we were launched using execv. See nsUpdateDriver.cpp.
-#if defined(XP_UNIX) && !defined(XP_MACOSX)
+#if defined(UNIX) && !defined(MACOSX)
#define USE_EXECV
#endif
@@ -115,12 +115,12 @@ static bool sUseHardLinks = true;
# define MAYBE_USE_HARD_LINKS 0
#endif
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX)
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(WNT) && !defined(MACOSX)
#include "nss.h"
#include "prerror.h"
#endif
-#ifdef XP_WIN
+#ifdef WNT
#include "updatehelper.h"
// Closes the handle if valid and if the updater is elevated returns with the
@@ -216,7 +216,7 @@ struct MARChannelStringTable {
typedef void (* ThreadFunc)(void *param);
-#ifdef XP_WIN
+#ifdef WNT
#include <process.h>
class Thread
@@ -252,7 +252,7 @@ private:
void *mThreadParam;
};
-#elif defined(XP_UNIX)
+#elif defined(UNIX)
#include <pthread.h>
class Thread
@@ -270,7 +270,6 @@ public:
private:
pthread_t thr;
};
-
#else
#error "Unsupported platform"
#endif
@@ -287,7 +286,7 @@ static bool sReplaceRequest = false;
static bool sUsingService = false;
static bool sIsOSUpdate = false;
-#ifdef XP_WIN
+#ifdef WNT
// The current working directory specified in the command line.
static NS_tchar* gDestPath;
static NS_tchar gCallbackRelPath[MAXPATHLEN];
@@ -352,7 +351,7 @@ EnvHasValue(const char *name)
return (val && *val);
}
-#ifdef XP_WIN
+#ifdef WNT
/**
* Coverts a relative update path to a full path for Windows.
*
@@ -406,7 +405,7 @@ get_valid_path(NS_tchar **line, bool isdir = false)
return nullptr;
}
-#ifdef XP_WIN
+#ifdef WNT
// All paths must be relative from the current working directory
if (path[0] == NS_T('\\') || path[1] == NS_T(':')) {
LOG(("get_valid_path: path must be relative: " LOG_S, path));
@@ -461,7 +460,7 @@ get_quoted_path(const NS_tchar *path)
static void ensure_write_permissions(const NS_tchar *path)
{
-#ifdef XP_WIN
+#ifdef WNT
(void) _wchmod(path, _S_IREAD | _S_IWRITE);
#else
struct stat fs;
@@ -605,7 +604,7 @@ static int ensure_parent_dir(const NS_tchar *path)
return rv;
}
-#ifdef XP_UNIX
+#ifdef UNIX
static int ensure_copy_symlink(const NS_tchar *path, const NS_tchar *dest)
{
// Copy symlinks by creating a new symlink to the same target
@@ -648,7 +647,7 @@ create_hard_link(const NS_tchar *srcFilename, const NS_tchar *destFilename)
// Copy the file named path onto a new file named dest.
static int ensure_copy(const NS_tchar *path, const NS_tchar *dest)
{
-#ifdef XP_WIN
+#ifdef WNT
// Fast path for Windows
bool result = CopyFileW(path, dest, false);
if (!result) {
@@ -666,7 +665,7 @@ static int ensure_copy(const NS_tchar *path, const NS_tchar *dest)
return READ_ERROR;
}
-#ifdef XP_UNIX
+#ifdef UNIX
if (S_ISLNK(ss.st_mode)) {
return ensure_copy_symlink(path, dest);
}
@@ -766,7 +765,7 @@ static int ensure_copy_recursive(const NS_tchar *path, const NS_tchar *dest,
return READ_ERROR;
}
-#ifdef XP_UNIX
+#ifdef UNIX
if (S_ISLNK(sInfo.st_mode)) {
return ensure_copy_symlink(path, dest);
}
@@ -859,7 +858,7 @@ static int rename_file(const NS_tchar *spath, const NS_tchar *dpath,
return OK;
}
-#ifdef XP_WIN
+#ifdef WNT
// Remove the directory pointed to by path and all of its files and
// sub-directories. If a file is in use move it to the tobedeleted directory
// and attempt to schedule removal of the file on reboot
@@ -967,7 +966,7 @@ static int backup_discard(const NS_tchar *path)
}
int rv = ensure_remove(backup);
-#if defined(XP_WIN)
+#if defined(WNT)
if (rv && !sStagedUpdate && !sReplaceRequest) {
LOG(("backup_discard: unable to remove: " LOG_S, backup));
NS_tchar path[MAXPATHLEN];
@@ -1311,7 +1310,7 @@ AddFile::Execute()
return rv;
}
-#ifdef XP_WIN
+#ifdef WNT
char sourcefile[MAXPATHLEN];
if (!WideCharToMultiByte(CP_UTF8, 0, mFile, -1, sourcefile, MAXPATHLEN,
nullptr, nullptr)) {
@@ -1465,7 +1464,7 @@ PatchFile::Prepare()
if (!fp)
return WRITE_ERROR;
-#ifdef XP_WIN
+#ifdef WNT
char sourcefile[MAXPATHLEN];
if (!WideCharToMultiByte(CP_UTF8, 0, mPatchFile, -1, sourcefile, MAXPATHLEN,
nullptr, nullptr)) {
@@ -1495,7 +1494,7 @@ PatchFile::Execute()
return rv;
FILE *origfile = nullptr;
-#ifdef XP_WIN
+#ifdef WNT
if (NS_tstrcmp(mFile, gCallbackRelPath) == 0) {
// Read from the copy of the callback when patching since the callback can't
// be opened for reading to prevent the application from being launched.
@@ -1537,7 +1536,7 @@ PatchFile::Execute()
#if defined(HAVE_POSIX_FALLOCATE)
AutoFile ofile(ensure_open(mFile, NS_T("wb+"), ss.st_mode));
posix_fallocate(fileno((FILE *)ofile), 0, header.dlen);
-#elif defined(XP_WIN)
+#elif defined(WNT)
bool shouldTruncate = true;
// Creating the file, setting the size, and then closing the file handle
// lessens fragmentation more than any other method tested. Other methods that
@@ -1565,7 +1564,7 @@ PatchFile::Execute()
AutoFile ofile(ensure_open(mFile, shouldTruncate ? NS_T("wb+") : NS_T("rb+"),
ss.st_mode));
-#elif defined(XP_MACOSX)
+#elif defined(MACOSX)
AutoFile ofile(ensure_open(mFile, NS_T("wb+"), ss.st_mode));
// Modified code from FileUtils.cpp
fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, header.dlen};
@@ -1589,7 +1588,7 @@ PatchFile::Execute()
return WRITE_ERROR_OPEN_PATCH_FILE;
}
-#ifdef XP_WIN
+#ifdef WNT
if (!shouldTruncate) {
fseek(ofile, 0, SEEK_SET);
}
@@ -1802,7 +1801,7 @@ PatchIfFile::Finish(int status)
//-----------------------------------------------------------------------------
-#ifdef XP_WIN
+#ifdef WNT
#include "nsWindowsRestart.cpp"
#include "nsWindowsHelpers.h"
#include "uachelper.h"
@@ -1827,9 +1826,9 @@ LaunchCallbackApp(const NS_tchar *workingDir,
#if defined(USE_EXECV)
execv(argv[0], argv);
-#elif defined(XP_MACOSX)
+#elif defined(MACOSX)
LaunchChild(argc, argv);
-#elif defined(XP_WIN)
+#elif defined(WNT)
// Do not allow the callback to run when running an update through the
// service as session 0. The unelevated updater.exe will do the launching.
if (!usingService) {
@@ -1915,7 +1914,7 @@ IsUpdateStatusPendingService()
}
#endif
-#ifdef XP_WIN
+#ifdef WNT
/*
* Read the update.status file and sets isSuccess to true if
* the status is set to succeeded.
@@ -1956,18 +1955,18 @@ static int
CopyInstallDirToDestDir()
{
// These files should not be copied over to the updated app
-#ifdef XP_WIN
+#ifdef WNT
#define SKIPLIST_COUNT 3
-#elif XP_MACOSX
+#elif MACOSX
#define SKIPLIST_COUNT 0
#else
#define SKIPLIST_COUNT 2
#endif
copy_recursive_skiplist<SKIPLIST_COUNT> skiplist;
-#ifndef XP_MACOSX
+#ifndef MACOSX
skiplist.append(0, gInstallDirPath, NS_T("updated"));
skiplist.append(1, gInstallDirPath, NS_T("updates/0"));
-#ifdef XP_WIN
+#ifdef WNT
skiplist.append(2, gInstallDirPath, NS_T("updated.update_in_progress.lock"));
#endif
#endif
@@ -1989,11 +1988,11 @@ ProcessReplaceRequest()
// 2. Move newDir to destDir. In case of failure, revert step 1 and abort.
// 3. Delete tmpDir (or defer it to the next reboot).
-#ifdef XP_MACOSX
+#ifdef MACOSX
NS_tchar destDir[MAXPATHLEN];
NS_tsnprintf(destDir, sizeof(destDir)/sizeof(destDir[0]),
NS_T("%s/Contents"), gInstallDirPath);
-#elif XP_WIN
+#elif WNT
// Windows preserves the case of the file/directory names. We use the
// GetLongPathName API in order to get the correct case for the directory
// name, so that if the user has used a different case when launching the
@@ -2013,7 +2012,7 @@ ProcessReplaceRequest()
NS_tchar newDir[MAXPATHLEN];
NS_tsnprintf(newDir, sizeof(newDir)/sizeof(newDir[0]),
-#ifdef XP_MACOSX
+#ifdef MACOSX
NS_T("%s/Contents"),
gWorkingDirPath);
#else
@@ -2030,7 +2029,7 @@ ProcessReplaceRequest()
LOG(("Begin moving destDir (" LOG_S ") to tmpDir (" LOG_S ")",
destDir, tmpDir));
int rv = rename_file(destDir, tmpDir, true);
-#ifdef XP_WIN
+#ifdef WNT
// On Windows, if Firefox is launched using the shortcut, it will hold a handle
// to its installation directory open, which might not get released in time.
// Therefore we wait a little bit here to see if the handle is released.
@@ -2057,7 +2056,7 @@ ProcessReplaceRequest()
LOG(("Begin moving newDir (" LOG_S ") to destDir (" LOG_S ")",
newDir, destDir));
rv = rename_file(newDir, destDir, true);
-#ifdef XP_MACOSX
+#ifdef MACOSX
if (rv) {
LOG(("Moving failed. Begin copying newDir (" LOG_S ") to destDir (" LOG_S ")",
newDir, destDir));
@@ -2082,7 +2081,7 @@ ProcessReplaceRequest()
rv = ensure_remove_recursive(tmpDir, true);
if (rv) {
LOG(("Removing tmpDir failed, err: %d", rv));
-#ifdef XP_WIN
+#ifdef WNT
NS_tchar deleteDir[MAXPATHLEN];
NS_tsnprintf(deleteDir, sizeof(deleteDir)/sizeof(deleteDir[0]),
NS_T("%s\\%s"), destDir, DELETE_DIR);
@@ -2096,7 +2095,7 @@ ProcessReplaceRequest()
#endif
}
-#ifdef XP_MACOSX
+#ifdef MACOSX
// On OS X, we we need to remove the staging directory after its Contents
// directory has been moved.
NS_tchar updatedAppDir[MAXPATHLEN];
@@ -2110,7 +2109,7 @@ ProcessReplaceRequest()
return 0;
}
-#ifdef XP_WIN
+#ifdef WNT
static void
WaitForServiceFinishThread(void *param)
{
@@ -2206,7 +2205,7 @@ UpdateThreadFunc(void *param)
#ifdef MOZ_VERIFY_MAR_SIGNATURE
if (rv == OK) {
-#ifdef XP_WIN
+#ifdef WNT
HKEY baseKey = nullptr;
wchar_t valueName[] = L"Image Path";
wchar_t rasenh[] = L"rsaenh.dll";
@@ -2232,7 +2231,7 @@ UpdateThreadFunc(void *param)
}
#endif
rv = gArchiveReader.VerifySignature();
-#ifdef XP_WIN
+#ifdef WNT
if (baseKey) {
if (reset) {
RegSetValueExW(baseKey, valueName, 0, REG_SZ,
@@ -2249,7 +2248,7 @@ UpdateThreadFunc(void *param)
NS_tchar updateSettingsPath[MAX_TEXT_LEN];
NS_tsnprintf(updateSettingsPath,
sizeof(updateSettingsPath) / sizeof(updateSettingsPath[0]),
-#ifdef XP_MACOSX
+#ifdef MACOSX
NS_T("%s/Contents/Resources/update-settings.ini"),
#else
NS_T("%s/update-settings.ini"),
@@ -2311,7 +2310,7 @@ UpdateThreadFunc(void *param)
if (rv) {
LOG(("failed: %d", rv));
} else {
-#ifdef XP_MACOSX
+#ifdef MACOSX
// If the update was successful we need to update the timestamp on the
// top-level Mac OS X bundle directory so that Mac OS X's Launch Services
// picks up any major changes when the bundle is updated.
@@ -2349,7 +2348,7 @@ int NS_main(int argc, NS_tchar **argv)
}
#endif
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX)
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(WNT) && !defined(MACOSX)
// On Windows and Mac we rely on native APIs to do verifications so we don't
// need to initialize NSS at all there.
// Otherwise, minimize the amount of NSS we depend on by avoiding all the NSS
@@ -2396,7 +2395,7 @@ int NS_main(int argc, NS_tchar **argv)
*slash = NS_T('\0');
}
-#ifdef XP_WIN
+#ifdef WNT
bool useService = false;
bool testOnlyFallbackKeyExists = false;
bool noServiceFallback = EnvHasValue("MOZ_NO_SERVICE_FALLBACK");
@@ -2432,13 +2431,13 @@ int NS_main(int argc, NS_tchar **argv)
#endif
// If there is a PID specified and it is not '0' then wait for the process to exit.
-#ifdef XP_WIN
+#ifdef WNT
__int64 pid = 0;
#else
int pid = 0;
#endif
if (argc > 4) {
-#ifdef XP_WIN
+#ifdef WNT
pid = _wtoi64(argv[4]);
#else
pid = atoi(argv[4]);
@@ -2473,10 +2472,10 @@ int NS_main(int argc, NS_tchar **argv)
if (sReplaceRequest) {
// If we're attempting to replace the application, try to append to the
// log generated when staging the staged update.
-#ifdef XP_WIN
+#ifdef WNT
NS_tchar* logDir = gPatchDirPath;
#else
-#ifdef XP_MACOSX
+#ifdef MACOSX
NS_tchar* logDir = gPatchDirPath;
#else
NS_tchar logDir[MAXPATHLEN];
@@ -2536,7 +2535,7 @@ int NS_main(int argc, NS_tchar **argv)
}
#endif
-#ifdef XP_WIN
+#ifdef WNT
if (pid > 0) {
HANDLE parent = OpenProcess(SYNCHRONIZE, false, (DWORD) pid);
// May return nullptr if the parent process has already gone away.
@@ -2556,7 +2555,7 @@ int NS_main(int argc, NS_tchar **argv)
#endif
if (sReplaceRequest) {
-#ifdef XP_WIN
+#ifdef WNT
// On Windows, the current working directory of the process should be changed
// so that it's not locked.
NS_tchar sysDir[MAX_PATH + 1] = { L'\0' };
@@ -2571,7 +2570,7 @@ int NS_main(int argc, NS_tchar **argv)
// argument prior to callbackIndex is the working directory.
const int callbackIndex = 6;
-#if defined(XP_WIN)
+#if defined(WNT)
sUsingService = EnvHasValue("MOZ_USING_SERVICE");
putenv(const_cast<char*>("MOZ_USING_SERVICE="));
// lastFallbackError keeps track of the last error for the service not being
@@ -2914,7 +2913,7 @@ int NS_main(int argc, NS_tchar **argv)
}
}
-#ifdef XP_WIN
+#ifdef WNT
// For replace requests, we don't need to do any real updates, so this is not
// necessary.
if (!sReplaceRequest) {
@@ -3102,7 +3101,7 @@ int NS_main(int argc, NS_tchar **argv)
NS_tmkdir(DELETE_DIR, 0755);
}
}
-#endif /* XP_WIN */
+#endif /* WNT */
// Run update process on a background thread. ShowProgressUI may return
// before QuitProgressUI has been called, so wait for UpdateThreadFunc to
@@ -3115,7 +3114,7 @@ int NS_main(int argc, NS_tchar **argv)
}
t.Join();
-#ifdef XP_WIN
+#ifdef WNT
if (argc > callbackIndex && !sReplaceRequest) {
if (callbackFile != INVALID_HANDLE_VALUE) {
CloseHandle(callbackFile);
@@ -3144,13 +3143,13 @@ int NS_main(int argc, NS_tchar **argv)
"directory: " LOG_S, DELETE_DIR));
}
}
-#endif /* XP_WIN */
+#endif /* WNT */
#if defined(MOZ_WIDGET_GONK)
} // end the extra level of scope for the GonkAutoMounter
#endif
-#ifdef XP_MACOSX
+#ifdef MACOSX
// When the update is successful remove the precomplete file in the root of
// the application bundle and move the distribution directory from
// Contents/MacOS to Contents/Resources and if both exist delete the
@@ -3188,12 +3187,12 @@ int NS_main(int argc, NS_tchar **argv)
}
}
}
-#endif /* XP_MACOSX */
+#endif /* MACOSX */
LogFinish();
if (argc > callbackIndex) {
-#if defined(XP_WIN)
+#if defined(WNT)
if (gSucceeded) {
// The service update will only be executed if it is already installed.
// For first time installs of the service, the install will happen from
@@ -3211,12 +3210,12 @@ int NS_main(int argc, NS_tchar **argv)
}
}
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 0);
-#endif /* XP_WIN */
-#ifdef XP_MACOSX
+#endif /* WNT */
+#ifdef MACOSX
if (gSucceeded) {
LaunchMacPostProcess(gInstallDirPath);
}
-#endif /* XP_MACOSX */
+#endif /* MACOSX */
LaunchCallbackApp(argv[5],
argc - callbackIndex,
argv + callbackIndex,
@@ -3342,7 +3341,7 @@ ActionList::Finish(int status)
}
-#ifdef XP_WIN
+#ifdef WNT
int add_dir_entries(const NS_tchar *dirpath, ActionList *list)
{
int rv = OK;
@@ -3649,7 +3648,7 @@ GetManifestContents(const NS_tchar *manifest)
mbuf[ms.st_size] = '\0';
rb = mbuf;
-#ifndef XP_WIN
+#ifndef WNT
return rb;
#else
NS_tchar *wrb = (NS_tchar *) malloc((ms.st_size + 1) * sizeof(NS_tchar));
@@ -3675,7 +3674,7 @@ int AddPreCompleteActions(ActionList *list)
return OK;
}
-#ifdef XP_MACOSX
+#ifdef MACOSX
NS_tchar *rb = GetManifestContents(NS_T("Contents/Resources/precomplete"));
#else
NS_tchar *rb = GetManifestContents(NS_T("precomplete"));
diff --git a/onlineupdate/source/update/updater/win_dirent.cpp b/onlineupdate/source/update/updater/win_dirent.cxx
index b0807ba5e193..7df6c26f2bbe 100644
--- a/onlineupdate/source/update/updater/win_dirent.cpp
+++ b/onlineupdate/source/update/updater/win_dirent.cxx
@@ -4,6 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifdef WNT
#include "win_dirent.h"
#include <errno.h>
#include <string.h>
@@ -75,4 +76,4 @@ dirent* readdir(DIR* dir)
sizeof(gDirEnt.d_name)/sizeof(gDirEnt.d_name[0]));
return &gDirEnt;
}
-
+#endif
diff --git a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx
new file mode 100644
index 000000000000..1193f867efa7
--- /dev/null
+++ b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx
@@ -0,0 +1,379 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsVersionComparator.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#if defined(WNT) && !defined(UPDATER_NO_STRING_GLUE_STL)
+#include <wchar.h>
+#include "nsStringGlue.h"
+#endif
+
+struct VersionPart
+{
+ int32_t numA;
+
+ const char* strB; // NOT null-terminated, can be a null pointer
+ uint32_t strBlen;
+
+ int32_t numC;
+
+ char* extraD; // null-terminated
+};
+
+#ifdef WNT
+struct VersionPartW
+{
+ int32_t numA;
+
+ wchar_t* strB; // NOT null-terminated, can be a null pointer
+ uint32_t strBlen;
+
+ int32_t numC;
+
+ wchar_t* extraD; // null-terminated
+
+};
+#endif
+
+/**
+ * Parse a version part into a number and "extra text".
+ *
+ * @returns A pointer to the next versionpart, or null if none.
+ */
+static char*
+ParseVP(char* aPart, VersionPart& aResult)
+{
+ char* dot;
+
+ aResult.numA = 0;
+ aResult.strB = nullptr;
+ aResult.strBlen = 0;
+ aResult.numC = 0;
+ aResult.extraD = nullptr;
+
+ if (!aPart) {
+ return aPart;
+ }
+
+ dot = strchr(aPart, '.');
+ if (dot) {
+ *dot = '\0';
+ }
+
+ if (aPart[0] == '*' && aPart[1] == '\0') {
+ aResult.numA = INT32_MAX;
+ aResult.strB = "";
+ } else {
+ aResult.numA = strtol(aPart, const_cast<char**>(&aResult.strB), 10);
+ }
+
+ if (!*aResult.strB) {
+ aResult.strB = nullptr;
+ aResult.strBlen = 0;
+ } else {
+ if (aResult.strB[0] == '+') {
+ static const char kPre[] = "pre";
+
+ ++aResult.numA;
+ aResult.strB = kPre;
+ aResult.strBlen = sizeof(kPre) - 1;
+ } else {
+ const char* numstart = strpbrk(aResult.strB, "0123456789+-");
+ if (!numstart) {
+ aResult.strBlen = strlen(aResult.strB);
+ } else {
+ aResult.strBlen = numstart - aResult.strB;
+
+ aResult.numC = strtol(numstart, &aResult.extraD, 10);
+ if (!*aResult.extraD) {
+ aResult.extraD = nullptr;
+ }
+ }
+ }
+ }
+
+ if (dot) {
+ ++dot;
+
+ if (!*dot) {
+ dot = nullptr;
+ }
+ }
+
+ return dot;
+}
+
+
+/**
+ * Parse a version part into a number and "extra text".
+ *
+ * @returns A pointer to the next versionpart, or null if none.
+ */
+#ifdef WNT
+static wchar_t*
+ParseVP(wchar_t* aPart, VersionPartW& aResult)
+{
+
+ wchar_t* dot;
+
+ aResult.numA = 0;
+ aResult.strB = nullptr;
+ aResult.strBlen = 0;
+ aResult.numC = 0;
+ aResult.extraD = nullptr;
+
+ if (!aPart) {
+ return aPart;
+ }
+
+ dot = wcschr(aPart, '.');
+ if (dot) {
+ *dot = '\0';
+ }
+
+ if (aPart[0] == '*' && aPart[1] == '\0') {
+ aResult.numA = INT32_MAX;
+ aResult.strB = L"";
+ } else {
+ aResult.numA = wcstol(aPart, const_cast<wchar_t**>(&aResult.strB), 10);
+ }
+
+ if (!*aResult.strB) {
+ aResult.strB = nullptr;
+ aResult.strBlen = 0;
+ } else {
+ if (aResult.strB[0] == '+') {
+ static wchar_t kPre[] = L"pre";
+
+ ++aResult.numA;
+ aResult.strB = kPre;
+ aResult.strBlen = sizeof(kPre) - 1;
+ } else {
+ const wchar_t* numstart = wcspbrk(aResult.strB, L"0123456789+-");
+ if (!numstart) {
+ aResult.strBlen = wcslen(aResult.strB);
+ } else {
+ aResult.strBlen = numstart - aResult.strB;
+
+ aResult.numC = wcstol(numstart, &aResult.extraD, 10);
+ if (!*aResult.extraD) {
+ aResult.extraD = nullptr;
+ }
+ }
+ }
+ }
+
+ if (dot) {
+ ++dot;
+
+ if (!*dot) {
+ dot = nullptr;
+ }
+ }
+
+ return dot;
+}
+#endif
+
+// compare two null-terminated strings, which may be null pointers
+static int32_t
+ns_strcmp(const char* aStr1, const char* aStr2)
+{
+ // any string is *before* no string
+ if (!aStr1) {
+ return aStr2 != 0;
+ }
+
+ if (!aStr2) {
+ return -1;
+ }
+
+ return strcmp(aStr1, aStr2);
+}
+
+// compare two length-specified string, which may be null pointers
+static int32_t
+ns_strnncmp(const char* aStr1, uint32_t aLen1,
+ const char* aStr2, uint32_t aLen2)
+{
+ // any string is *before* no string
+ if (!aStr1) {
+ return aStr2 != 0;
+ }
+
+ if (!aStr2) {
+ return -1;
+ }
+
+ for (; aLen1 && aLen2; --aLen1, --aLen2, ++aStr1, ++aStr2) {
+ if (*aStr1 < *aStr2) {
+ return -1;
+ }
+
+ if (*aStr1 > *aStr2) {
+ return 1;
+ }
+ }
+
+ if (aLen1 == 0) {
+ return aLen2 == 0 ? 0 : -1;
+ }
+
+ return 1;
+}
+
+// compare two int32_t
+static int32_t
+ns_cmp(int32_t aNum1, int32_t aNum2)
+{
+ if (aNum1 < aNum2) {
+ return -1;
+ }
+
+ return aNum1 != aNum2;
+}
+
+/**
+ * Compares two VersionParts
+ */
+static int32_t
+CompareVP(VersionPart& aVer1, VersionPart& aVer2)
+{
+ int32_t r = ns_cmp(aVer1.numA, aVer2.numA);
+ if (r) {
+ return r;
+ }
+
+ r = ns_strnncmp(aVer1.strB, aVer1.strBlen, aVer2.strB, aVer2.strBlen);
+ if (r) {
+ return r;
+ }
+
+ r = ns_cmp(aVer1.numC, aVer2.numC);
+ if (r) {
+ return r;
+ }
+
+ return ns_strcmp(aVer1.extraD, aVer2.extraD);
+}
+
+/**
+ * Compares two VersionParts
+ */
+#ifdef WNT
+static int32_t
+CompareVP(VersionPartW& aVer1, VersionPartW& aVer2)
+{
+ int32_t r = ns_cmp(aVer1.numA, aVer2.numA);
+ if (r) {
+ return r;
+ }
+
+ r = wcsncmp(aVer1.strB, aVer2.strB, XPCOM_MIN(aVer1.strBlen, aVer2.strBlen));
+ if (r) {
+ return r;
+ }
+
+ r = ns_cmp(aVer1.numC, aVer2.numC);
+ if (r) {
+ return r;
+ }
+
+ if (!aVer1.extraD) {
+ return aVer2.extraD != 0;
+ }
+
+ if (!aVer2.extraD) {
+ return -1;
+ }
+
+ return wcscmp(aVer1.extraD, aVer2.extraD);
+}
+#endif
+
+namespace mozilla {
+
+#ifdef WNT
+int32_t
+CompareVersions(const char16_t* aStrA, const char16_t* aStrB)
+{
+ wchar_t* A2 = wcsdup(char16ptr_t(aStrA));
+ if (!A2) {
+ return 1;
+ }
+
+ wchar_t* B2 = wcsdup(char16ptr_t(aStrB));
+ if (!B2) {
+ free(A2);
+ return 1;
+ }
+
+ int32_t result;
+ wchar_t* a = A2;
+ wchar_t* b = B2;
+
+ do {
+ VersionPartW va, vb;
+
+ a = ParseVP(a, va);
+ b = ParseVP(b, vb);
+
+ result = CompareVP(va, vb);
+ if (result) {
+ break;
+ }
+
+ } while (a || b);
+
+ free(A2);
+ free(B2);
+
+ return result;
+}
+#endif
+
+int32_t
+CompareVersions(const char* aStrA, const char* aStrB)
+{
+ char* A2 = strdup(aStrA);
+ if (!A2) {
+ return 1;
+ }
+
+ char* B2 = strdup(aStrB);
+ if (!B2) {
+ free(A2);
+ return 1;
+ }
+
+ int32_t result;
+ char* a = A2;
+ char* b = B2;
+
+ do {
+ VersionPart va, vb;
+
+ a = ParseVP(a, va);
+ b = ParseVP(b, vb);
+
+ result = CompareVP(va, vb);
+ if (result) {
+ break;
+ }
+
+ } while (a || b);
+
+ free(A2);
+ free(B2);
+
+ return result;
+}
+
+} // namespace mozilla
+
diff --git a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h
new file mode 100644
index 000000000000..431d181ef722
--- /dev/null
+++ b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsVersionComparator_h__
+#define nsVersionComparator_h__
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#if defined(WNT) && !defined(UPDATER_NO_STRING_GLUE_STL)
+#include <wchar.h>
+#include "nsStringGlue.h"
+#endif
+
+/**
+ * In order to compare version numbers in Mozilla, you need to use the
+ * mozilla::Version class. You can construct an object of this type by passing
+ * in a string version number to the constructor. Objects of this type can be
+ * compared using the standard comparison operators.
+ *
+ * For example, let's say that you want to make sure that a given version
+ * number is not older than 15.a2. Here's how you would write a function to
+ * do that.
+ *
+ * bool IsVersionValid(const char* version) {
+ * return mozilla::Version("15.a2") <= mozilla::Version(version);
+ * }
+ *
+ * Or, since Version's constructor is implicit, you can simplify this code:
+ *
+ * bool IsVersionValid(const char* version) {
+ * return mozilla::Version("15.a2") <= version;
+ * }
+ *
+ * On Windows, if your version strings are wide characters, you should use the
+ * mozilla::VersionW variant instead. The semantics of that class is the same
+ * as Version.
+ */
+
+namespace mozilla {
+
+int32_t CompareVersions(const char* aStrA, const char* aStrB);
+
+#ifdef WNT
+int32_t CompareVersions(const char16_t* aStrA, const char16_t* aStrB);
+#endif
+
+struct Version
+{
+ explicit Version(const char* aVersionString)
+ {
+ versionContent = strdup(aVersionString);
+ }
+
+ const char* ReadContent() const
+ {
+ return versionContent;
+ }
+
+ ~Version()
+ {
+ free(versionContent);
+ }
+
+ bool operator<(const Version& aRhs) const
+ {
+ return CompareVersions(versionContent, aRhs.ReadContent()) == -1;
+ }
+ bool operator<=(const Version& aRhs) const
+ {
+ return CompareVersions(versionContent, aRhs.ReadContent()) < 1;
+ }
+ bool operator>(const Version& aRhs) const
+ {
+ return CompareVersions(versionContent, aRhs.ReadContent()) == 1;
+ }
+ bool operator>=(const Version& aRhs) const
+ {
+ return CompareVersions(versionContent, aRhs.ReadContent()) > -1;
+ }
+ bool operator==(const Version& aRhs) const
+ {
+ return CompareVersions(versionContent, aRhs.ReadContent()) == 0;
+ }
+ bool operator!=(const Version& aRhs) const
+ {
+ return CompareVersions(versionContent, aRhs.ReadContent()) != 0;
+ }
+ bool operator<(const char* aRhs) const
+ {
+ return CompareVersions(versionContent, aRhs) == -1;
+ }
+ bool operator<=(const char* aRhs) const
+ {
+ return CompareVersions(versionContent, aRhs) < 1;
+ }
+ bool operator>(const char* aRhs) const
+ {
+ return CompareVersions(versionContent, aRhs) == 1;
+ }
+ bool operator>=(const char* aRhs) const
+ {
+ return CompareVersions(versionContent, aRhs) > -1;
+ }
+ bool operator==(const char* aRhs) const
+ {
+ return CompareVersions(versionContent, aRhs) == 0;
+ }
+ bool operator!=(const char* aRhs) const
+ {
+ return CompareVersions(versionContent, aRhs) != 0;
+ }
+
+private:
+ char* versionContent;
+};
+
+#ifdef WNT
+struct VersionW
+{
+ VersionW(const char16_t* aVersionStringW)
+ {
+ versionContentW =
+ reinterpret_cast<char16_t*>(wcsdup(char16ptr_t(aVersionStringW)));
+ }
+
+ const char16_t* ReadContentW() const
+ {
+ return versionContentW;
+ }
+
+ ~VersionW()
+ {
+ free(versionContentW);
+ }
+
+ bool operator<(const VersionW& aRhs) const
+ {
+ return CompareVersions(versionContentW, aRhs.ReadContentW()) == -1;
+ }
+ bool operator<=(const VersionW& aRhs) const
+ {
+ return CompareVersions(versionContentW, aRhs.ReadContentW()) < 1;
+ }
+ bool operator>(const VersionW& aRhs) const
+ {
+ return CompareVersions(versionContentW, aRhs.ReadContentW()) == 1;
+ }
+ bool operator>=(const VersionW& aRhs) const
+ {
+ return CompareVersions(versionContentW, aRhs.ReadContentW()) > -1;
+ }
+ bool operator==(const VersionW& aRhs) const
+ {
+ return CompareVersions(versionContentW, aRhs.ReadContentW()) == 0;
+ }
+ bool operator!=(const VersionW& aRhs) const
+ {
+ return CompareVersions(versionContentW, aRhs.ReadContentW()) != 0;
+ }
+
+private:
+ char16_t* versionContentW;
+};
+#endif
+
+} // namespace mozilla
+
+#endif // nsVersionComparator_h__
+