summaryrefslogtreecommitdiff
path: root/staging/xulrunner
diff options
context:
space:
mode:
Diffstat (limited to 'staging/xulrunner')
-rw-r--r--staging/xulrunner/PKGBUILD63
-rw-r--r--staging/xulrunner/mozconfig56
-rw-r--r--staging/xulrunner/mozilla-pkgconfig.patch60
-rw-r--r--staging/xulrunner/port_gnomevfs_to_gio.patch1316
-rw-r--r--staging/xulrunner/xulrunner-omnijar.patch1737
-rw-r--r--staging/xulrunner/xulrunner-version.patch12
6 files changed, 3244 insertions, 0 deletions
diff --git a/staging/xulrunner/PKGBUILD b/staging/xulrunner/PKGBUILD
new file mode 100644
index 000000000..d9ad07e87
--- /dev/null
+++ b/staging/xulrunner/PKGBUILD
@@ -0,0 +1,63 @@
+# $Id: PKGBUILD 126161 2011-06-01 20:45:14Z ibiru $
+# Maintainer: Jan de Groot <jgc@archlinux.org>
+# Contributor: Alexander Baldeck <alexander@archlinux.org>
+pkgname=xulrunner
+pkgver=2.0.1
+_ffoxver=4.0.1
+pkgrel=2
+pkgdesc="Mozilla Runtime Environment"
+arch=('i686' 'x86_64')
+license=('MPL' 'GPL' 'LGPL')
+depends=('gtk2' 'gcc-libs' 'libidl2' 'mozilla-common' 'nss' 'libxt' 'libxrender' 'hunspell' 'startup-notification' 'mime-types' 'dbus-glib' 'alsa-lib' 'libevent' 'sqlite3>=3.7.4' 'libnotify')
+makedepends=('zip' 'pkg-config' 'diffutils' 'python2' 'wireless_tools' 'yasm' 'mesa')
+url="http://wiki.mozilla.org/XUL:Xul_Runner"
+source=(http://releases.mozilla.org/pub/mozilla.org/firefox/releases/${_ffoxver}/source/firefox-${_ffoxver}.source.tar.bz2
+ mozconfig
+ mozilla-pkgconfig.patch
+ xulrunner-version.patch
+ xulrunner-omnijar.patch
+ port_gnomevfs_to_gio.patch)
+options=('!emptydirs')
+md5sums=('9abda7d23151e97913c8555a64c13f34'
+ '2358a2ddd35bcdd62ff42442dfe548d9'
+ '639ea80e823543dd415b90c0ee804186'
+ 'a0236f6c3e55f60b7888d8cf137ff209'
+ '0bf82bc6677e3ce57fd20a147fe8d7b1'
+ '42f83468b296452fb754a81a4317ca64')
+build() {
+ cd "${srcdir}/mozilla-2.0"
+ cp "${srcdir}/mozconfig" .mozconfig
+
+ #fix libdir/sdkdir - fedora
+ patch -Np1 -i "${srcdir}/mozilla-pkgconfig.patch"
+
+ #Force installation to the same path for every version
+ patch -Np1 -i "${srcdir}/xulrunner-version.patch"
+
+ #https://bugzilla.mozilla.org/show_bug.cgi?id=620931
+ patch -Np1 -i "${srcdir}/xulrunner-omnijar.patch"
+
+ #https://bugzilla.mozilla.org/show_bug.cgi?id=494163
+ patch -Np1 -i "${srcdir}/port_gnomevfs_to_gio.patch"
+
+ unset CFLAGS
+ unset CXXFLAGS
+
+ export CXXFLAGS="-fpermissive"
+
+ make -j1 -f client.mk build MOZ_MAKE_FLAGS="$MAKEFLAGS"
+}
+
+package() {
+ cd "${srcdir}/mozilla-2.0"
+ make -j1 -f client.mk DESTDIR="${pkgdir}" install
+
+ #Remove included dictionaries, add symlink to system myspell path.
+ #Note: this will cause file conflicts when users have installed dictionaries in the old location
+ rm -rf "${pkgdir}/usr/lib/xulrunner-2.0/dictionaries"
+ ln -sf /usr/share/myspell/dicts "${pkgdir}/usr/lib/xulrunner-2.0/dictionaries"
+
+ # add xulrunner library path to ld.so.conf
+ install -d ${pkgdir}/etc/ld.so.conf.d
+ echo "/usr/lib/xulrunner-2.0" > ${pkgdir}/etc/ld.so.conf.d/xulrunner.conf
+}
diff --git a/staging/xulrunner/mozconfig b/staging/xulrunner/mozconfig
new file mode 100644
index 000000000..03a352920
--- /dev/null
+++ b/staging/xulrunner/mozconfig
@@ -0,0 +1,56 @@
+. $topsrcdir/xulrunner/config/mozconfig
+
+ac_add_options --prefix=/usr
+ac_add_options --libdir=/usr/lib
+ac_add_options --with-system-nspr
+ac_add_options --with-system-nss
+ac_add_options --with-system-jpeg
+ac_add_options --with-system-zlib
+ac_add_options --with-system-bz2
+ac_add_options --with-system-png
+ac_add_options --with-system-libevent
+ac_add_options --enable-system-hunspell
+ac_add_options --enable-system-sqlite
+ac_add_options --enable-system-cairo
+ac_add_options --with-pthreads
+
+ac_add_options --enable-default-toolkit=cairo-gtk2
+ac_add_options --enable-safe-browsing
+ac_add_options --enable-extensions=default
+ac_add_options --enable-startup-notification
+ac_add_options --enable-pango
+ac_add_options --enable-svg
+ac_add_options --enable-canvas
+ac_add_options --enable-smil
+ac_add_options --enable-canvas3d
+ac_add_options --enable-places
+ac_add_options --enable-shared-js
+ac_add_options --enable-url-classifier
+
+ac_add_options --enable-optimize
+ac_add_options --enable-strip
+ac_add_options --enable-install-strip
+ac_add_options --enable-jemalloc
+ac_add_options --enable-xterm-updates
+ac_add_options --enable-printing
+ac_add_options --enable-xinerama
+
+ac_add_options --disable-javaxpcom
+ac_add_options --disable-crashreporter
+ac_add_options --disable-updater
+ac_add_options --disable-tests
+ac_add_options --disable-xprint
+ac_add_options --disable-mochitest
+ac_add_options --disable-debug
+ac_add_options --disable-installer
+ac_add_options --disable-pedantic
+
+ac_add_options --enable-gio
+ac_add_options --disable-gnomevfs
+ac_add_options --enable-gconf
+ac_add_options --enable-libnotify
+
+export BUILD_OFFICIAL=1
+export MOZILLA_OFFICIAL=1
+mk_add_options BUILD_OFFICIAL=1
+mk_add_options MOZILLA_OFFICIAL=1
diff --git a/staging/xulrunner/mozilla-pkgconfig.patch b/staging/xulrunner/mozilla-pkgconfig.patch
new file mode 100644
index 000000000..2203efcde
--- /dev/null
+++ b/staging/xulrunner/mozilla-pkgconfig.patch
@@ -0,0 +1,60 @@
+diff -Nur mozilla-2.0.orig/xulrunner/installer/libxul-embedding.pc.in mozilla-2.0/xulrunner/installer/libxul-embedding.pc.in
+--- mozilla-2.0.orig/xulrunner/installer/libxul-embedding.pc.in 2011-03-03 14:12:04.000000000 -0800
++++ mozilla-2.0/xulrunner/installer/libxul-embedding.pc.in 2011-03-13 03:25:12.350027359 -0700
+@@ -6,5 +6,6 @@
+ Name: libxul-embedding
+ Description: Static library for version-independent embedding of the Mozilla runtime
+ Version: %MOZILLA_VERSION%
++Requires: %NSPR_NAME% >= %NSPR_VERSION%
+ Libs: -L${sdkdir}/lib -lxpcomglue -ldl
+ Cflags: -DXPCOM_GLUE -I${includedir} %WCHAR_CFLAGS%
+diff -Nur mozilla-2.0.orig/xulrunner/installer/libxul.pc.in mozilla-2.0/xulrunner/installer/libxul.pc.in
+--- mozilla-2.0.orig/xulrunner/installer/libxul.pc.in 2011-03-03 14:12:04.000000000 -0800
++++ mozilla-2.0/xulrunner/installer/libxul.pc.in 2011-03-13 03:25:28.010027359 -0700
+@@ -1,5 +1,6 @@
+ prefix=%prefix%
+ sdkdir=%sdkdir%
++libdir=%libdir%
+ includedir=%includedir%
+ idldir=%idldir%
+
+diff -Nur mozilla-2.0.orig/xulrunner/installer/Makefile.in mozilla-2.0/xulrunner/installer/Makefile.in
+--- mozilla-2.0.orig/xulrunner/installer/Makefile.in 2011-03-03 14:12:04.000000000 -0800
++++ mozilla-2.0/xulrunner/installer/Makefile.in 2011-03-13 03:25:55.570027359 -0700
+@@ -121,6 +121,7 @@
+ -e "s|%includedir%|$(includedir)|" \
+ -e "s|%idldir%|$(idldir)|" \
+ -e "s|%sdkdir%|$(sdkdir)|" \
++ -e "s|%libdir%|$(installdir)|" \
+ -e "s|%MOZ_APP_NAME%|$(MOZ_APP_NAME)|" \
+ -e "s|%MOZILLA_VERSION%|$(MOZ_APP_VERSION)|" \
+ -e "s|%WCHAR_CFLAGS%|$(WCHAR_CFLAGS)|" \
+diff -Nur mozilla-2.0.orig/xulrunner/installer/mozilla-gtkmozembed-embedding.pc.in mozilla-2.0/xulrunner/installer/mozilla-gtkmozembed-embedding.pc.in
+--- mozilla-2.0.orig/xulrunner/installer/mozilla-gtkmozembed-embedding.pc.in 2011-03-03 14:12:04.000000000 -0800
++++ mozilla-2.0/xulrunner/installer/mozilla-gtkmozembed-embedding.pc.in 2011-03-13 03:26:18.676694023 -0700
+@@ -1,5 +1,6 @@
+ prefix=%prefix%
+ sdkdir=%sdkdir%
++libdir=%libdir%
+ includedir=%includedir%
+
+ Name: mozilla-gtkembedmoz
+diff -Nur mozilla-2.0.orig/xulrunner/installer/mozilla-gtkmozembed.pc.in mozilla-2.0/xulrunner/installer/mozilla-gtkmozembed.pc.in
+--- mozilla-2.0.orig/xulrunner/installer/mozilla-gtkmozembed.pc.in 2011-03-03 14:12:04.000000000 -0800
++++ mozilla-2.0/xulrunner/installer/mozilla-gtkmozembed.pc.in 2011-03-13 03:26:41.566694025 -0700
+@@ -1,5 +1,6 @@
+ prefix=%prefix%
+ sdkdir=%sdkdir%
++libdir=%libdir%
+ includedir=%includedir%
+
+ Name: mozilla-gtkembedmoz
+diff -Nur mozilla-2.0.orig/xulrunner/installer/mozilla-js.pc.in mozilla-2.0/xulrunner/installer/mozilla-js.pc.in
+--- mozilla-2.0.orig/xulrunner/installer/mozilla-js.pc.in 2011-03-03 14:12:04.000000000 -0800
++++ mozilla-2.0/xulrunner/installer/mozilla-js.pc.in 2011-03-13 03:27:19.680027357 -0700
+@@ -7,4 +7,4 @@
+ Version: %MOZILLA_VERSION%
+ Requires: %NSPR_NAME% >= %NSPR_VERSION%
+ Libs: -L${sdkdir}/lib %MOZ_JS_LINK%
+-Cflags: -I${includedir} -DXP_UNIX -DJS_THREADSAFE
++Cflags: -I${includedir} -I${includedir}/js -DXP_UNIX -DJS_THREADSAFE
diff --git a/staging/xulrunner/port_gnomevfs_to_gio.patch b/staging/xulrunner/port_gnomevfs_to_gio.patch
new file mode 100644
index 000000000..797baff42
--- /dev/null
+++ b/staging/xulrunner/port_gnomevfs_to_gio.patch
@@ -0,0 +1,1316 @@
+diff -r 49a1b2aa43c5 extensions/gio/Makefile.in
+--- /dev/null Thu Jan 01 00:00:00 1970 +0000
++++ b/extensions/gio/Makefile.in Tue Jan 11 11:17:52 2011 +0100
+@@ -0,0 +1,69 @@
++# vim:set ts=8 sw=8 sts=8 noet:
++# ***** BEGIN LICENSE BLOCK *****
++# Version: MPL 1.1/GPL 2.0/LGPL 2.1
++#
++# The contents of this file are subject to the Mozilla Public License Version
++# 1.1 (the "License"); you may not use this file except in compliance with
++# the License. You may obtain a copy of the License at
++# http://www.mozilla.org/MPL/
++#
++# Software distributed under the License is distributed on an "AS IS" basis,
++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
++# for the specific language governing rights and limitations under the
++# License.
++#
++# The Original Code is the Mozilla gnome-vfs extension.
++#
++# The Initial Developer of the Original Code is IBM Corporation.
++#
++# Portions created by IBM Corporation are Copyright (C) 2004
++# IBM Corporation. All Rights Reserved.
++#
++# Contributor(s):
++# Darin Fisher <darin@meer.net>
++# Jan Horak <jhorak@redhat.com>
++#
++# Alternatively, the contents of this file may be used under the terms of
++# either the GNU General Public License Version 2 or later (the "GPL"), or
++# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++# in which case the provisions of the GPL or the LGPL are applicable instead
++# of those above. If you wish to allow use of your version of this file only
++# under the terms of either the GPL or the LGPL, and not to allow others to
++# use your version of this file under the terms of the MPL, indicate your
++# decision by deleting the provisions above and replace them with the notice
++# and other provisions required by the GPL or the LGPL. If you do not delete
++# the provisions above, a recipient may use your version of this file under
++# the terms of any one of the MPL, the GPL or the LGPL.
++#
++# ***** END LICENSE BLOCK *****
++
++DEPTH = ../..
++topsrcdir = @top_srcdir@
++srcdir = @srcdir@
++VPATH = @srcdir@
++
++include $(DEPTH)/config/autoconf.mk
++
++MODULE = nkgio
++LIBRARY_NAME = nkgio
++SHORT_LIBNAME = nkgio
++IS_COMPONENT = 1
++
++CPPSRCS = \
++ nsGIOProtocolHandler.cpp \
++ $(NULL)
++
++LOCAL_INCLUDES = $(MOZ_GIO_CFLAGS)
++
++EXTRA_DSO_LDOPTS = \
++ $(XPCOM_GLUE_LDOPTS) \
++ $(NSPR_LIBS) \
++ $(MOZ_GIO_LIBS) \
++ $(NULL)
++
++# make sure this component is never statically linked into the main
++# application. this is necessary since we don't want to force users
++# to install gio in order to use the rest of mozilla ;-)
++FORCE_SHARED_LIB= 1
++
++include $(topsrcdir)/config/rules.mk
+diff -r 49a1b2aa43c5 extensions/gio/makefiles.sh
+--- /dev/null Thu Jan 01 00:00:00 1970 +0000
++++ b/extensions/gio/makefiles.sh Tue Jan 11 11:17:52 2011 +0100
+@@ -0,0 +1,41 @@
++#! /bin/sh
++# ***** BEGIN LICENSE BLOCK *****
++# Version: MPL 1.1/GPL 2.0/LGPL 2.1
++#
++# The contents of this file are subject to the Mozilla Public License Version
++# 1.1 (the "License"); you may not use this file except in compliance with
++# the License. You may obtain a copy of the License at
++# http://www.mozilla.org/MPL/
++#
++# Software distributed under the License is distributed on an "AS IS" basis,
++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
++# for the specific language governing rights and limitations under the
++# License.
++#
++# The Original Code is Mozilla Build System
++#
++# The Initial Developer of the Original Code is
++# Ben Turner <mozilla@songbirdnest.com>
++#
++# Portions created by the Initial Developer are Copyright (C) 2007
++# the Initial Developer. All Rights Reserved.
++#
++# Contributor(s):
++#
++# Alternatively, the contents of this file may be used under the terms of
++# either the GNU General Public License Version 2 or later (the "GPL"), or
++# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++# in which case the provisions of the GPL or the LGPL are applicable instead
++# of those above. If you wish to allow use of your version of this file only
++# under the terms of either the GPL or the LGPL, and not to allow others to
++# use your version of this file under the terms of the MPL, indicate your
++# decision by deleting the provisions above and replace them with the notice
++# and other provisions required by the GPL or the LGPL. If you do not delete
++# the provisions above, a recipient may use your version of this file under
++# the terms of any one of the MPL, the GPL or the LGPL.
++#
++# ***** END LICENSE BLOCK *****
++
++add_makefiles "
++ extensions/gio/Makefile
++"
+diff -r 49a1b2aa43c5 extensions/gio/nsGIOProtocolHandler.cpp
+--- /dev/null Thu Jan 01 00:00:00 1970 +0000
++++ b/extensions/gio/nsGIOProtocolHandler.cpp Tue Jan 11 11:17:52 2011 +0100
+@@ -0,0 +1,1163 @@
++/* vim:set ts=2 sw=2 et cindent: */
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
++ * for the specific language governing rights and limitations under the
++ * License.
++ *
++ * The Original Code is the Mozilla gnome-vfs extension.
++ *
++ * The Initial Developer of the Original Code is IBM Corporation.
++ *
++ * Portions created by IBM Corporation are Copyright (C) 2004
++ * IBM Corporation. All Rights Reserved.
++ *
++ * Contributor(s):
++ * Darin Fisher <darin@meer.net>
++ * Jan Horak <jhorak@redhat.com>
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++/*
++ * This code is based on original Mozilla gnome-vfs extension. It implements
++ * input stream provided by GVFS/GIO.
++*/
++#include "mozilla/ModuleUtils.h"
++#include "nsIPrefService.h"
++#include "nsIPrefBranch2.h"
++#include "nsIObserver.h"
++#include "nsThreadUtils.h"
++#include "nsProxyRelease.h"
++#include "nsIStringBundle.h"
++#include "nsIStandardURL.h"
++#include "nsMimeTypes.h"
++#include "nsNetUtil.h"
++#include "mozilla/Monitor.h"
++#include <gio/gio.h>
++
++#define MOZ_GIO_SCHEME "moz-gio"
++#define MOZ_GIO_SUPPORTED_PROTOCOLS "network.gio.supported-protocols"
++
++//-----------------------------------------------------------------------------
++
++// NSPR_LOG_MODULES=gio:5
++#ifdef PR_LOGGING
++static PRLogModuleInfo *sGIOLog;
++#define LOG(args) PR_LOG(sGIOLog, PR_LOG_DEBUG, args)
++#else
++#define LOG(args)
++#endif
++
++
++//-----------------------------------------------------------------------------
++static nsresult
++MapGIOResult(gint code)
++{
++ switch (code)
++ {
++ case G_IO_ERROR_NOT_FOUND: return NS_ERROR_FILE_NOT_FOUND; // shows error
++ case G_IO_ERROR_INVALID_ARGUMENT: return NS_ERROR_INVALID_ARG;
++ case G_IO_ERROR_NOT_SUPPORTED: return NS_ERROR_NOT_AVAILABLE;
++ case G_IO_ERROR_NO_SPACE: return NS_ERROR_FILE_NO_DEVICE_SPACE;
++ case G_IO_ERROR_READ_ONLY: return NS_ERROR_FILE_READ_ONLY;
++ case G_IO_ERROR_PERMISSION_DENIED: return NS_ERROR_FILE_ACCESS_DENIED; // wrong password/login
++ case G_IO_ERROR_CLOSED: return NS_BASE_STREAM_CLOSED; // was EOF
++ case G_IO_ERROR_NOT_DIRECTORY: return NS_ERROR_FILE_NOT_DIRECTORY;
++ case G_IO_ERROR_PENDING: return NS_ERROR_IN_PROGRESS;
++ case G_IO_ERROR_EXISTS: return NS_ERROR_FILE_ALREADY_EXISTS;
++ case G_IO_ERROR_IS_DIRECTORY: return NS_ERROR_FILE_IS_DIRECTORY;
++ case G_IO_ERROR_NOT_MOUNTED: return NS_ERROR_NOT_CONNECTED; // shows error
++ case G_IO_ERROR_HOST_NOT_FOUND: return NS_ERROR_UNKNOWN_HOST; // shows error
++ case G_IO_ERROR_CANCELLED: return NS_ERROR_ABORT;
++ case G_IO_ERROR_NOT_EMPTY: return NS_ERROR_FILE_DIR_NOT_EMPTY;
++ case G_IO_ERROR_FILENAME_TOO_LONG: return NS_ERROR_FILE_NAME_TOO_LONG;
++ case G_IO_ERROR_INVALID_FILENAME: return NS_ERROR_FILE_INVALID_PATH;
++ case G_IO_ERROR_TIMED_OUT: return NS_ERROR_NET_TIMEOUT; // shows error
++ case G_IO_ERROR_WOULD_BLOCK: return NS_BASE_STREAM_WOULD_BLOCK;
++ case G_IO_ERROR_FAILED_HANDLED: return NS_ERROR_ABORT; // Cancel on login dialog
++
++/* unhandled:
++ G_IO_ERROR_NOT_REGULAR_FILE,
++ G_IO_ERROR_NOT_SYMBOLIC_LINK,
++ G_IO_ERROR_NOT_MOUNTABLE_FILE,
++ G_IO_ERROR_TOO_MANY_LINKS,
++ G_IO_ERROR_ALREADY_MOUNTED,
++ G_IO_ERROR_CANT_CREATE_BACKUP,
++ G_IO_ERROR_WRONG_ETAG,
++ G_IO_ERROR_WOULD_RECURSE,
++ G_IO_ERROR_BUSY,
++ G_IO_ERROR_WOULD_MERGE,
++ G_IO_ERROR_TOO_MANY_OPEN_FILES
++*/
++ // Make GCC happy
++ default:
++ return NS_ERROR_FAILURE;
++ }
++
++ return NS_ERROR_FAILURE;
++}
++
++static nsresult
++MapGIOResult(GError *result)
++{
++ if (!result)
++ return NS_OK;
++ else
++ return MapGIOResult(result->code);
++}
++/** Return values for mount operation.
++ * These enums are used as mount operation return values.
++ */
++typedef enum {
++ MOUNT_OPERATION_IN_PROGRESS, /** \enum operation in progress */
++ MOUNT_OPERATION_SUCCESS, /** \enum operation successful */
++ MOUNT_OPERATION_FAILED /** \enum operation not successful */
++} MountOperationResult;
++//-----------------------------------------------------------------------------
++/**
++ * Sort function compares according to file type (directory/file)
++ * and alphabethical order
++ * @param a pointer to GFileInfo object to compare
++ * @param b pointer to GFileInfo object to compare
++ * @return -1 when first object should be before the second, 0 when equal,
++ * +1 when second object should be before the first
++ */
++static gint
++FileInfoComparator(gconstpointer a, gconstpointer b)
++{
++ GFileInfo *ia = ( GFileInfo *) a;
++ GFileInfo *ib = ( GFileInfo *) b;
++ if (g_file_info_get_file_type(ia) == G_FILE_TYPE_DIRECTORY
++ && g_file_info_get_file_type(ib) != G_FILE_TYPE_DIRECTORY)
++ return -1;
++ if (g_file_info_get_file_type(ib) == G_FILE_TYPE_DIRECTORY
++ && g_file_info_get_file_type(ia) != G_FILE_TYPE_DIRECTORY)
++ return 1;
++
++ return strcasecmp(g_file_info_get_name(ia), g_file_info_get_name(ib));
++}
++
++/* Declaration of mount callback functions */
++static void mount_enclosing_volume_finished (GObject *source_object,
++ GAsyncResult *res,
++ gpointer user_data);
++static void mount_operation_ask_password (GMountOperation *mount_op,
++ const char *message,
++ const char *default_user,
++ const char *default_domain,
++ GAskPasswordFlags flags,
++ gpointer user_data);
++//-----------------------------------------------------------------------------
++
++class nsGIOInputStream : public nsIInputStream
++{
++ public:
++ NS_DECL_ISUPPORTS
++ NS_DECL_NSIINPUTSTREAM
++
++ nsGIOInputStream(const nsCString &uriSpec)
++ : mSpec(uriSpec)
++ , mChannel(nsnull)
++ , mHandle(nsnull)
++ , mStream(nsnull)
++ , mBytesRemaining(PR_UINT32_MAX)
++ , mStatus(NS_OK)
++ , mDirList(nsnull)
++ , mDirListPtr(nsnull)
++ , mDirBufCursor(0)
++ , mDirOpen(PR_FALSE)
++ , mMonitorMountInProgress("GIOInputStream::MountFinished") { }
++
++ ~nsGIOInputStream() { Close(); }
++
++ void SetChannel(nsIChannel *channel)
++ {
++ // We need to hold an owning reference to our channel. This is done
++ // so we can access the channel's notification callbacks to acquire
++ // a reference to a nsIAuthPrompt if we need to handle an interactive
++ // mount operation.
++ //
++ // However, the channel can only be accessed on the main thread, so
++ // we have to be very careful with ownership. Moreover, it doesn't
++ // support threadsafe addref/release, so proxying is the answer.
++ //
++ // Also, it's important to note that this likely creates a reference
++ // cycle since the channel likely owns this stream. This reference
++ // cycle is broken in our Close method.
++
++ NS_ADDREF(mChannel = channel);
++ }
++ void SetMountResult(MountOperationResult result, gint error_code);
++ private:
++ nsresult DoOpen();
++ nsresult DoRead(char *aBuf, PRUint32 aCount, PRUint32 *aCountRead);
++ nsresult SetContentTypeOfChannel(const char *contentType);
++ nsresult MountVolume();
++ nsresult DoOpenDirectory();
++ nsresult DoOpenFile(GFileInfo *info);
++ nsCString mSpec;
++ nsIChannel *mChannel; // manually refcounted
++ GFile *mHandle;
++ GFileInputStream *mStream;
++ PRUint64 mBytesRemaining;
++ nsresult mStatus;
++ GList *mDirList;
++ GList *mDirListPtr;
++ nsCString mDirBuf;
++ PRUint32 mDirBufCursor;
++ PRPackedBool mDirOpen;
++ MountOperationResult mMountRes;
++ mozilla::Monitor mMonitorMountInProgress;
++ gint mMountErrorCode;
++};
++/**
++ * Set result of mount operation and notify monitor waiting for results.
++ * This method is called in main thread as long as it is used only
++ * in mount_enclosing_volume_finished function.
++ * @param result Result of mount operation
++ */
++void
++nsGIOInputStream::SetMountResult(MountOperationResult result, gint error_code)
++{
++ mozilla::MonitorAutoEnter mon(mMonitorMountInProgress);
++ mMountRes = result;
++ mMountErrorCode = error_code;
++ mon.Notify();
++}
++
++/**
++ * Start mount operation and wait in loop until it is finished. This method is
++ * called from thread which is trying to read from location.
++ */
++nsresult
++nsGIOInputStream::MountVolume() {
++ GMountOperation* mount_op = g_mount_operation_new();
++ g_signal_connect (mount_op, "ask-password",
++ G_CALLBACK (mount_operation_ask_password), mChannel);
++ mMountRes = MOUNT_OPERATION_IN_PROGRESS;
++ /* g_file_mount_enclosing_volume uses a dbus request to mount the volume.
++ Callback mount_enclosing_volume_finished is called in main thread
++ (not this thread on which this method is called). */
++ g_file_mount_enclosing_volume(mHandle,
++ G_MOUNT_MOUNT_NONE,
++ mount_op,
++ NULL,
++ mount_enclosing_volume_finished,
++ this);
++ mozilla::MonitorAutoEnter mon(mMonitorMountInProgress);
++ /* Waiting for finish of mount operation thread */
++ while (mMountRes == MOUNT_OPERATION_IN_PROGRESS)
++ mon.Wait();
++
++ g_object_unref(mount_op);
++
++ if (mMountRes == MOUNT_OPERATION_FAILED) {
++ return MapGIOResult(mMountErrorCode);
++ } else {
++ return NS_OK;
++ }
++}
++
++/**
++ * Create list of infos about objects in opened directory
++ * Return: NS_OK when list obtained, otherwise error code according
++ * to failed operation.
++ */
++nsresult
++nsGIOInputStream::DoOpenDirectory()
++{
++ GError *error = NULL;
++
++ GFileEnumerator *f_enum = g_file_enumerate_children(mHandle,
++ "standard::*,time::*",
++ G_FILE_QUERY_INFO_NONE,
++ NULL,
++ &error);
++ if (!f_enum) {
++ nsresult rv = MapGIOResult(error);
++ g_warning("Cannot read from directory: %s", error->message);
++ g_error_free(error);
++ return rv;
++ }
++ // fill list of file infos
++ GFileInfo *info = g_file_enumerator_next_file(f_enum, NULL, &error);
++ while (info) {
++ mDirList = g_list_append(mDirList, info);
++ info = g_file_enumerator_next_file(f_enum, NULL, &error);
++ }
++ g_object_unref(f_enum);
++ if (error) {
++ g_warning("Error reading directory content: %s", error->message);
++ nsresult rv = MapGIOResult(error);
++ g_error_free(error);
++ return rv;
++ }
++ mDirOpen = PR_TRUE;
++
++ // Sort list of file infos by using FileInfoComparator function
++ mDirList = g_list_sort(mDirList, FileInfoComparator);
++ mDirListPtr = mDirList;
++
++ // Write base URL (make sure it ends with a '/')
++ mDirBuf.Append("300: ");
++ mDirBuf.Append(mSpec);
++ if (mSpec.get()[mSpec.Length() - 1] != '/')
++ mDirBuf.Append('/');
++ mDirBuf.Append('\n');
++
++ // Write column names
++ mDirBuf.Append("200: filename content-length last-modified file-type\n");
++
++ // Write charset (assume UTF-8)
++ // XXX is this correct?
++ mDirBuf.Append("301: UTF-8\n");
++ SetContentTypeOfChannel(APPLICATION_HTTP_INDEX_FORMAT);
++ return NS_OK;
++}
++
++/**
++ * Create file stream and set mime type for channel
++ * @param info file info used to determine mime type
++ * @return NS_OK when file stream created successfuly, error code otherwise
++ */
++nsresult
++nsGIOInputStream::DoOpenFile(GFileInfo *info)
++{
++ GError *error = NULL;
++
++ mStream = g_file_read(mHandle, NULL, &error);
++ if (!mStream) {
++ nsresult rv = MapGIOResult(error);
++ g_warning("Cannot read from file: %s", error->message);
++ g_error_free(error);
++ return rv;
++ }
++
++ const char * content_type = g_file_info_get_content_type(info);
++ if (content_type) {
++ char *mime_type = g_content_type_get_mime_type(content_type);
++ if (mime_type) {
++ if (strcmp(mime_type, APPLICATION_OCTET_STREAM) != 0) {
++ SetContentTypeOfChannel(mime_type);
++ }
++ g_free(mime_type);
++ }
++ } else {
++ g_warning("Missing content type.");
++ }
++
++ mBytesRemaining = g_file_info_get_size(info);
++ // Update the content length attribute on the channel. We do this
++ // synchronously without proxying. This hack is not as bad as it looks!
++ mChannel->SetContentLength(mBytesRemaining);
++
++ return NS_OK;
++}
++
++/**
++ * Start file open operation, mount volume when needed and according to file type
++ * create file output stream or read directory content.
++ * @return NS_OK when file or directory opened successfully, error code otherwise
++ */
++nsresult
++nsGIOInputStream::DoOpen()
++{
++ nsresult rv;
++ GError *error = NULL;
++
++ NS_ASSERTION(mHandle == nsnull, "already open");
++
++ mHandle = g_file_new_for_uri( mSpec.get() );
++
++ GFileInfo *info = g_file_query_info(mHandle,
++ "standard::*",
++ G_FILE_QUERY_INFO_NONE,
++ NULL,
++ &error);
++
++ if (error) {
++ if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_MOUNTED) {
++ // location is not yet mounted, try to mount
++ g_error_free(error);
++ if (NS_IsMainThread())
++ return NS_ERROR_NOT_CONNECTED;
++ error = NULL;
++ rv = MountVolume();
++ if (rv != NS_OK) {
++ return rv;
++ }
++ // get info again
++ info = g_file_query_info(mHandle,
++ "standard::*",
++ G_FILE_QUERY_INFO_NONE,
++ NULL,
++ &error);
++ // second try to get file info from remote files after media mount
++ if (!info) {
++ g_warning("Unable to get file info: %s", error->message);
++ rv = MapGIOResult(error);
++ g_error_free(error);
++ return rv;
++ }
++ } else {
++ g_warning("Unable to get file info: %s", error->message);
++ rv = MapGIOResult(error);
++ g_error_free(error);
++ return rv;
++ }
++ }
++ // Get file type to handle directories and file differently
++ GFileType f_type = g_file_info_get_file_type(info);
++ if (f_type == G_FILE_TYPE_DIRECTORY) {
++ // directory
++ rv = DoOpenDirectory();
++ } else if (f_type != G_FILE_TYPE_UNKNOWN) {
++ // file
++ rv = DoOpenFile(info);
++ } else {
++ g_warning("Unable to get file type.");
++ rv = NS_ERROR_FILE_NOT_FOUND;
++ }
++ if (info)
++ g_object_unref(info);
++ return rv;
++}
++
++/**
++ * Read content of file or create file list from directory
++ * @param aBuf read destination buffer
++ * @param aCount length of destination buffer
++ * @param aCountRead number of read characters
++ * @return NS_OK when read successfully, NS_BASE_STREAM_CLOSED when end of file,
++ * error code otherwise
++ */
++nsresult
++nsGIOInputStream::DoRead(char *aBuf, PRUint32 aCount, PRUint32 *aCountRead)
++{
++ nsresult rv = NS_ERROR_NOT_AVAILABLE;
++ if (mStream) {
++ // file read
++ GError *error = NULL;
++ PRUint32 bytes_read = g_input_stream_read(G_INPUT_STREAM(mStream),
++ aBuf,
++ aCount,
++ NULL,
++ &error);
++ if (error) {
++ rv = MapGIOResult(error);
++ *aCountRead = 0;
++ g_warning("Cannot read from file: %s", error->message);
++ g_error_free(error);
++ return rv;
++ }
++ *aCountRead = bytes_read;
++ mBytesRemaining -= *aCountRead;
++ return NS_OK;
++ }
++ else if (mDirOpen) {
++ // directory read
++ while (aCount && rv != NS_BASE_STREAM_CLOSED)
++ {
++ // Copy data out of our buffer
++ PRUint32 bufLen = mDirBuf.Length() - mDirBufCursor;
++ if (bufLen)
++ {
++ PRUint32 n = PR_MIN(bufLen, aCount);
++ memcpy(aBuf, mDirBuf.get() + mDirBufCursor, n);
++ *aCountRead += n;
++ aBuf += n;
++ aCount -= n;
++ mDirBufCursor += n;
++ }
++
++ if (!mDirListPtr) // Are we at the end of the directory list?
++ {
++ rv = NS_BASE_STREAM_CLOSED;
++ }
++ else if (aCount) // Do we need more data?
++ {
++ GFileInfo *info = (GFileInfo *) mDirListPtr->data;
++
++ // Prune '.' and '..' from directory listing.
++ const char * fname = g_file_info_get_name(info);
++ if (fname && fname[0] == '.' &&
++ (fname[1] == '\0' || (fname[1] == '.' && fname[2] == '\0')))
++ {
++ mDirListPtr = mDirListPtr->next;
++ continue;
++ }
++
++ mDirBuf.Assign("201: ");
++
++ // The "filename" field
++ nsCString escName;
++ nsCOMPtr<nsINetUtil> nu = do_GetService(NS_NETUTIL_CONTRACTID);
++ if (nu && fname) {
++ nu->EscapeString(nsDependentCString(fname),
++ nsINetUtil::ESCAPE_URL_PATH, escName);
++
++ mDirBuf.Append(escName);
++ mDirBuf.Append(' ');
++ }
++
++ // The "content-length" field
++ // XXX truncates size from 64-bit to 32-bit
++ mDirBuf.AppendInt(PRInt32(g_file_info_get_size(info)));
++ mDirBuf.Append(' ');
++
++ // The "last-modified" field
++ //
++ // NSPR promises: PRTime is compatible with time_t
++ // we just need to convert from seconds to microseconds
++ GTimeVal gtime;
++ g_file_info_get_modification_time(info, &gtime);
++
++ PRExplodedTime tm;
++ PRTime pt = ((PRTime) gtime.tv_sec) * 1000000;
++ PR_ExplodeTime(pt, PR_GMTParameters, &tm);
++ {
++ char buf[64];
++ PR_FormatTimeUSEnglish(buf, sizeof(buf),
++ "%a,%%20%d%%20%b%%20%Y%%20%H:%M:%S%%20GMT ", &tm);
++ mDirBuf.Append(buf);
++ }
++
++ // The "file-type" field
++ switch (g_file_info_get_file_type(info))
++ {
++ case G_FILE_TYPE_REGULAR:
++ mDirBuf.Append("FILE ");
++ break;
++ case G_FILE_TYPE_DIRECTORY:
++ mDirBuf.Append("DIRECTORY ");
++ break;
++ case G_FILE_TYPE_SYMBOLIC_LINK:
++ mDirBuf.Append("SYMBOLIC-LINK ");
++ break;
++ default:
++ break;
++ }
++ mDirBuf.Append('\n');
++
++ mDirBufCursor = 0;
++ mDirListPtr = mDirListPtr->next;
++ }
++ }
++ }
++ return rv;
++}
++
++/**
++ * This class is used to implement SetContentTypeOfChannel.
++ */
++class nsGIOSetContentTypeEvent : public nsRunnable
++{
++ public:
++ nsGIOSetContentTypeEvent(nsIChannel *channel, const char *contentType)
++ : mChannel(channel), mContentType(contentType)
++ {
++ // stash channel reference in mChannel. no AddRef here! see note
++ // in SetContentTypeOfchannel.
++ }
++
++ NS_IMETHOD Run()
++ {
++ mChannel->SetContentType(mContentType);
++ return NS_OK;
++ }
++
++ private:
++ nsIChannel *mChannel;
++ nsCString mContentType;
++};
++
++nsresult
++nsGIOInputStream::SetContentTypeOfChannel(const char *contentType)
++{
++ // We need to proxy this call over to the main thread. We post an
++ // asynchronous event in this case so that we don't delay reading data, and
++ // we know that this is safe to do since the channel's reference will be
++ // released asynchronously as well. We trust the ordering of the main
++ // thread's event queue to protect us against memory corruption.
++
++ nsresult rv;
++ nsCOMPtr<nsIRunnable> ev =
++ new nsGIOSetContentTypeEvent(mChannel, contentType);
++ if (!ev)
++ {
++ rv = NS_ERROR_OUT_OF_MEMORY;
++ }
++ else
++ {
++ rv = NS_DispatchToMainThread(ev);
++ }
++ return rv;
++}
++
++NS_IMPL_THREADSAFE_ISUPPORTS1(nsGIOInputStream, nsIInputStream)
++
++/**
++ * Free all used memory and close stream.
++ */
++NS_IMETHODIMP
++nsGIOInputStream::Close()
++{
++ if (mStream)
++ {
++ g_object_unref(mStream);
++ mStream = nsnull;
++ }
++
++ if (mHandle)
++ {
++ g_object_unref(mHandle);
++ mHandle = nsnull;
++ }
++
++ if (mDirList)
++ {
++ // Destroy the list of GIOFileInfo objects...
++ g_list_foreach(mDirList, (GFunc) g_object_unref, nsnull);
++ g_list_free(mDirList);
++ mDirList = nsnull;
++ mDirListPtr = nsnull;
++ }
++
++ if (mChannel)
++ {
++ nsresult rv = NS_OK;
++
++ nsCOMPtr<nsIThread> thread = do_GetMainThread();
++ if (thread)
++ rv = NS_ProxyRelease(thread, mChannel);
++
++ NS_ASSERTION(thread && NS_SUCCEEDED(rv), "leaking channel reference");
++ mChannel = nsnull;
++ }
++
++ mSpec.Truncate(); // free memory
++
++ // Prevent future reads from re-opening the handle.
++ if (NS_SUCCEEDED(mStatus))
++ mStatus = NS_BASE_STREAM_CLOSED;
++
++ return NS_OK;
++}
++
++/**
++ * Return number of remaining bytes available on input
++ * @param aResult remaining bytes
++ */
++NS_IMETHODIMP
++nsGIOInputStream::Available(PRUint32 *aResult)
++{
++ if (NS_FAILED(mStatus))
++ return mStatus;
++
++ /* When remaining bytes are bigger than max PRUint32 value an aResult must
++ be set to PRUint32 maximum */
++ if (mBytesRemaining > PR_UINT32_MAX)
++ *aResult = PR_UINT32_MAX;
++ else
++ *aResult = mBytesRemaining;
++
++ return NS_OK;
++}
++
++/**
++ * Trying to read from stream. When location is not available it tries to mount it.
++ * @param aBuf buffer to put read data
++ * @param aCount length of aBuf
++ * @param aCountRead number of bytes actually read
++ */
++NS_IMETHODIMP
++nsGIOInputStream::Read(char *aBuf,
++ PRUint32 aCount,
++ PRUint32 *aCountRead)
++{
++ *aCountRead = 0;
++ // Check if file is already opened, otherwise open it
++ if (!mStream && !mDirOpen && mStatus == NS_OK) {
++ mStatus = DoOpen();
++ if (NS_FAILED(mStatus)) {
++ return mStatus;
++ }
++ }
++
++ mStatus = DoRead(aBuf, aCount, aCountRead);
++ // Check if all data has been read
++ if (mStatus == NS_BASE_STREAM_CLOSED)
++ return NS_OK;
++
++ // Check whenever any error appears while reading
++ return mStatus;
++}
++
++NS_IMETHODIMP
++nsGIOInputStream::ReadSegments(nsWriteSegmentFun aWriter,
++ void *aClosure,
++ PRUint32 aCount,
++ PRUint32 *aResult)
++{
++ // There is no way to implement this using GnomeVFS, but fortunately
++ // that doesn't matter. Because we are a blocking input stream, Necko
++ // isn't going to call our ReadSegments method.
++ NS_NOTREACHED("nsGIOInputStream::ReadSegments");
++ return NS_ERROR_NOT_IMPLEMENTED;
++}
++
++NS_IMETHODIMP
++nsGIOInputStream::IsNonBlocking(PRBool *aResult)
++{
++ *aResult = PR_FALSE;
++ return NS_OK;
++}
++
++//-----------------------------------------------------------------------------
++
++/**
++ * Called when finishing mount operation. Result of operation is set in
++ * nsGIOInputStream. This function is called in main thread as an async request
++ * typically from dbus.
++ * @param source_object GFile object which requested the mount
++ * @param res result object
++ * @param user_data pointer to nsGIOInputStream
++ */
++static void
++mount_enclosing_volume_finished (GObject *source_object,
++ GAsyncResult *res,
++ gpointer user_data)
++{
++ GError *error = NULL;
++
++ nsGIOInputStream* istream = static_cast<nsGIOInputStream*>(user_data);
++
++ g_file_mount_enclosing_volume_finish(G_FILE (source_object), res, &error);
++
++ if (error) {
++ g_warning("Mount failed: %s %d", error->message, error->code);
++ istream->SetMountResult(MOUNT_OPERATION_FAILED, error->code);
++ g_error_free(error);
++ } else {
++ istream->SetMountResult(MOUNT_OPERATION_SUCCESS, 0);
++ }
++}
++
++/**
++ * This function is called when username or password are requested from user.
++ * This function is called in main thread as async request from dbus.
++ * @param mount_op mount operation
++ * @param message message to show to user
++ * @param default_user preffered user
++ * @param default_domain domain name
++ * @param flags what type of information is required
++ * @param user_data nsIChannel
++ */
++static void
++mount_operation_ask_password (GMountOperation *mount_op,
++ const char *message,
++ const char *default_user,
++ const char *default_domain,
++ GAskPasswordFlags flags,
++ gpointer user_data)
++{
++ nsIChannel *channel = (nsIChannel *) user_data;
++ if (!channel) {
++ g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED);
++ return;
++ }
++ // We can't handle request for domain
++ if (flags & G_ASK_PASSWORD_NEED_DOMAIN) {
++ g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED);
++ return;
++ }
++
++ nsCOMPtr<nsIAuthPrompt> prompt;
++ NS_QueryNotificationCallbacks(channel, prompt);
++
++ // If no auth prompt, then give up. We could failover to using the
++ // WindowWatcher service, but that might defeat a consumer's purposeful
++ // attempt to disable authentication (for whatever reason).
++ if (!prompt) {
++ g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED);
++ return;
++ }
++ // Parse out the host and port...
++ nsCOMPtr<nsIURI> uri;
++ channel->GetURI(getter_AddRefs(uri));
++ if (!uri) {
++ g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED);
++ return;
++ }
++
++ nsCAutoString scheme, hostPort;
++ uri->GetScheme(scheme);
++ uri->GetHostPort(hostPort);
++
++ // It doesn't make sense for either of these strings to be empty. What kind
++ // of funky URI is this?
++ if (scheme.IsEmpty() || hostPort.IsEmpty()) {
++ g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED);
++ return;
++ }
++ // Construct the single signon key. Altering the value of this key will
++ // cause people's remembered passwords to be forgotten. Think carefully
++ // before changing the way this key is constructed.
++ nsAutoString key, realm;
++
++ NS_ConvertUTF8toUTF16 dispHost(scheme);
++ dispHost.Append(NS_LITERAL_STRING("://"));
++ dispHost.Append(NS_ConvertUTF8toUTF16(hostPort));
++
++ key = dispHost;
++ if (*default_domain != '\0')
++ {
++ // We assume the realm string is ASCII. That might be a bogus assumption,
++ // but we have no idea what encoding GnomeVFS is using, so for now we'll
++ // limit ourselves to ISO-Latin-1. XXX What is a better solution?
++ realm.Append('"');
++ realm.Append(NS_ConvertASCIItoUTF16(default_domain));
++ realm.Append('"');
++ key.Append(' ');
++ key.Append(realm);
++ }
++ // Construct the message string...
++ //
++ // We use Necko's string bundle here. This code really should be encapsulated
++ // behind some Necko API, after all this code is based closely on the code in
++ // nsHttpChannel.cpp.
++ nsCOMPtr<nsIStringBundleService> bundleSvc =
++ do_GetService(NS_STRINGBUNDLE_CONTRACTID);
++ if (!bundleSvc) {
++ g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED);
++ return;
++ }
++ nsCOMPtr<nsIStringBundle> bundle;
++ bundleSvc->CreateBundle("chrome://global/locale/commonDialogs.properties",
++ getter_AddRefs(bundle));
++ if (!bundle) {
++ g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED);
++ return;
++ }
++ nsAutoString nsmessage;
++
++ if (flags & G_ASK_PASSWORD_NEED_PASSWORD) {
++ if (flags & G_ASK_PASSWORD_NEED_USERNAME) {
++ if (!realm.IsEmpty()) {
++ const PRUnichar *strings[] = { realm.get(), dispHost.get() };
++ bundle->FormatStringFromName(NS_LITERAL_STRING("EnterLoginForRealm").get(),
++ strings, 2, getter_Copies(nsmessage));
++ } else {
++ const PRUnichar *strings[] = { dispHost.get() };
++ bundle->FormatStringFromName(NS_LITERAL_STRING("EnterUserPasswordFor").get(),
++ strings, 1, getter_Copies(nsmessage));
++ }
++ } else {
++ NS_ConvertUTF8toUTF16 userName(default_user);
++ const PRUnichar *strings[] = { userName.get(), dispHost.get() };
++ bundle->FormatStringFromName(NS_LITERAL_STRING("EnterPasswordFor").get(),
++ strings, 2, getter_Copies(nsmessage));
++ }
++ } else {
++ g_warning("Unknown mount operation request (flags: %x)", flags);
++ }
++
++ if (nsmessage.IsEmpty()) {
++ g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED);
++ return;
++ }
++ // Prompt the user...
++ nsresult rv;
++ PRBool retval = PR_FALSE;
++ PRUnichar *user = nsnull, *pass = nsnull;
++ if (default_user) {
++ // user will be freed by PromptUsernameAndPassword
++ user = ToNewUnicode(NS_ConvertUTF8toUTF16(default_user));
++ }
++ if (flags & G_ASK_PASSWORD_NEED_USERNAME) {
++ rv = prompt->PromptUsernameAndPassword(nsnull, nsmessage.get(),
++ key.get(),
++ nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
++ &user, &pass, &retval);
++ } else {
++ rv = prompt->PromptPassword(nsnull, nsmessage.get(),
++ key.get(),
++ nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
++ &pass, &retval);
++ }
++ if (NS_FAILED(rv) || !retval) { // was || user == '\0' || pass == '\0'
++ g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED);
++ return;
++ }
++ /* GIO should accept UTF8 */
++ g_mount_operation_set_username(mount_op, NS_ConvertUTF16toUTF8(user).get());
++ g_mount_operation_set_password(mount_op, NS_ConvertUTF16toUTF8(pass).get());
++ nsMemory::Free(user);
++ nsMemory::Free(pass);
++ g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_HANDLED);
++}
++
++//-----------------------------------------------------------------------------
++
++class nsGIOProtocolHandler : public nsIProtocolHandler
++ , public nsIObserver
++{
++ public:
++ NS_DECL_ISUPPORTS
++ NS_DECL_NSIPROTOCOLHANDLER
++ NS_DECL_NSIOBSERVER
++
++ nsresult Init();
++
++ private:
++ void InitSupportedProtocolsPref(nsIPrefBranch *prefs);
++ PRBool IsSupportedProtocol(const nsCString &spec);
++
++ nsCString mSupportedProtocols;
++};
++
++NS_IMPL_ISUPPORTS2(nsGIOProtocolHandler, nsIProtocolHandler, nsIObserver)
++
++nsresult
++nsGIOProtocolHandler::Init()
++{
++#ifdef PR_LOGGING
++ sGIOLog = PR_NewLogModule("gio");
++#endif
++
++ nsCOMPtr<nsIPrefBranch2> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
++ if (prefs)
++ {
++ InitSupportedProtocolsPref(prefs);
++ prefs->AddObserver(MOZ_GIO_SUPPORTED_PROTOCOLS, this, PR_FALSE);
++ }
++
++ return NS_OK;
++}
++
++void
++nsGIOProtocolHandler::InitSupportedProtocolsPref(nsIPrefBranch *prefs)
++{
++ // Get user preferences to determine which protocol is supported.
++ // Gvfs/GIO has a set of supported protocols like obex, network, archive,
++ // computer, dav, cdda, gphoto2, trash, etc. Some of these seems to be
++ // irrelevant to process by browser. By default accept only smb and sftp
++ // protocols so far.
++ nsresult rv = prefs->GetCharPref(MOZ_GIO_SUPPORTED_PROTOCOLS,
++ getter_Copies(mSupportedProtocols));
++ if (NS_SUCCEEDED(rv)) {
++ mSupportedProtocols.StripWhitespace();
++ ToLowerCase(mSupportedProtocols);
++ }
++ else
++ mSupportedProtocols.Assign("smb:,sftp:"); // use defaults
++
++ LOG(("gio: supported protocols \"%s\"\n", mSupportedProtocols.get()));
++}
++
++PRBool
++nsGIOProtocolHandler::IsSupportedProtocol(const nsCString &aSpec)
++{
++ const char *specString = aSpec.get();
++ const char *colon = strchr(specString, ':');
++ if (!colon)
++ return PR_FALSE;
++
++ PRUint32 length = colon - specString + 1;
++
++ // <scheme> + ':'
++ nsCString scheme(specString, length);
++
++ char *found = PL_strcasestr(mSupportedProtocols.get(), scheme.get());
++ if (!found)
++ return PR_FALSE;
++
++ if (found[length] != ',' && found[length] != '\0')
++ return PR_FALSE;
++
++ return PR_TRUE;
++}
++
++NS_IMETHODIMP
++nsGIOProtocolHandler::GetScheme(nsACString &aScheme)
++{
++ aScheme.Assign(MOZ_GIO_SCHEME);
++ return NS_OK;
++}
++
++NS_IMETHODIMP
++nsGIOProtocolHandler::GetDefaultPort(PRInt32 *aDefaultPort)
++{
++ *aDefaultPort = -1;
++ return NS_OK;
++}
++
++NS_IMETHODIMP
++nsGIOProtocolHandler::GetProtocolFlags(PRUint32 *aProtocolFlags)
++{
++ // Is URI_STD true of all GnomeVFS URI types?
++ *aProtocolFlags = URI_STD | URI_DANGEROUS_TO_LOAD;
++ return NS_OK;
++}
++
++NS_IMETHODIMP
++nsGIOProtocolHandler::NewURI(const nsACString &aSpec,
++ const char *aOriginCharset,
++ nsIURI *aBaseURI,
++ nsIURI **aResult)
++{
++ const nsCString flatSpec(aSpec);
++ LOG(("gio: NewURI [spec=%s]\n", flatSpec.get()));
++
++ if (!aBaseURI)
++ {
++ // XXX Is it good to support all GIO protocols?
++ if (!IsSupportedProtocol(flatSpec))
++ return NS_ERROR_UNKNOWN_PROTOCOL;
++
++ PRInt32 colon_location = flatSpec.FindChar(':');
++ if (colon_location <= 0)
++ return NS_ERROR_UNKNOWN_PROTOCOL;
++
++ // Verify that GIO supports this URI scheme.
++ PRBool uri_scheme_supported = PR_FALSE;
++
++ GVfs *gvfs = g_vfs_get_default();
++
++ if (!gvfs) {
++ g_warning("Cannot get GVfs object.");
++ return NS_ERROR_UNKNOWN_PROTOCOL;
++ }
++
++ const gchar* const * uri_schemes = g_vfs_get_supported_uri_schemes(gvfs);
++
++ while (*uri_schemes != NULL) {
++ // While flatSpec ends with ':' the uri_scheme does not. Therefore do not
++ // compare last character.
++ if (StringHead(flatSpec, colon_location).Equals(*uri_schemes)) {
++ uri_scheme_supported = PR_TRUE;
++ break;
++ }
++ uri_schemes++;
++ }
++
++ if (!uri_scheme_supported) {
++ return NS_ERROR_UNKNOWN_PROTOCOL;
++ }
++ }
++
++ nsresult rv;
++ nsCOMPtr<nsIStandardURL> url =
++ do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
++ if (NS_FAILED(rv))
++ return rv;
++
++ rv = url->Init(nsIStandardURL::URLTYPE_STANDARD, -1, flatSpec,
++ aOriginCharset, aBaseURI);
++ if (NS_SUCCEEDED(rv))
++ rv = CallQueryInterface(url, aResult);
++ return rv;
++
++}
++
++NS_IMETHODIMP
++nsGIOProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **aResult)
++{
++ NS_ENSURE_ARG_POINTER(aURI);
++ nsresult rv;
++
++ nsCAutoString spec;
++ rv = aURI->GetSpec(spec);
++ if (NS_FAILED(rv))
++ return rv;
++
++ nsRefPtr<nsGIOInputStream> stream = new nsGIOInputStream(spec);
++ if (!stream)
++ {
++ rv = NS_ERROR_OUT_OF_MEMORY;
++ }
++ else
++ {
++ // start out assuming an unknown content-type. we'll set the content-type
++ // to something better once we open the URI.
++ rv = NS_NewInputStreamChannel(aResult,
++ aURI,
++ stream,
++ NS_LITERAL_CSTRING(UNKNOWN_CONTENT_TYPE));
++ if (NS_SUCCEEDED(rv))
++ stream->SetChannel(*aResult);
++ }
++ return rv;
++}
++
++NS_IMETHODIMP
++nsGIOProtocolHandler::AllowPort(PRInt32 aPort,
++ const char *aScheme,
++ PRBool *aResult)
++{
++ // Don't override anything.
++ *aResult = PR_FALSE;
++ return NS_OK;
++}
++
++NS_IMETHODIMP
++nsGIOProtocolHandler::Observe(nsISupports *aSubject,
++ const char *aTopic,
++ const PRUnichar *aData)
++{
++ if (strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
++ nsCOMPtr<nsIPrefBranch> prefs = do_QueryInterface(aSubject);
++ InitSupportedProtocolsPref(prefs);
++ }
++ return NS_OK;
++}
++
++//-----------------------------------------------------------------------------
++
++#define NS_GIOPROTOCOLHANDLER_CID \
++{ /* ee706783-3af8-4d19-9e84-e2ebfe213480 */ \
++ 0xee706783, \
++ 0x3af8, \
++ 0x4d19, \
++ {0x9e, 0x84, 0xe2, 0xeb, 0xfe, 0x21, 0x34, 0x80} \
++}
++
++NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGIOProtocolHandler, Init)
++NS_DEFINE_NAMED_CID(NS_GIOPROTOCOLHANDLER_CID);
++
++static const mozilla::Module::CIDEntry kVFSCIDs[] = {
++ { &kNS_GIOPROTOCOLHANDLER_CID, false, NULL, nsGIOProtocolHandlerConstructor },
++ { NULL }
++};
++
++static const mozilla::Module::ContractIDEntry kVFSContracts[] = {
++ { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MOZ_GIO_SCHEME, &kNS_GIOPROTOCOLHANDLER_CID },
++ { NULL }
++};
++
++static const mozilla::Module kVFSModule = {
++ mozilla::Module::kVersion,
++ kVFSCIDs,
++ kVFSContracts
++};
++
++NSMODULE_DEFN(nsGIOModule) = &kVFSModule;
+diff -r 49a1b2aa43c5 netwerk/base/src/nsIOService.cpp
+--- a/netwerk/base/src/nsIOService.cpp Tue Dec 21 12:42:59 2010 +0100
++++ b/netwerk/base/src/nsIOService.cpp Tue Jan 11 11:17:52 2011 +0100
+@@ -454,6 +454,27 @@
+ }
+
+ #ifdef MOZ_X11
++ // check to see whether GVFS can handle this URI scheme. if it can
++ // create a nsIURI for the "scheme:", then we assume it has support for
++ // the requested protocol. otherwise, we failover to using the default
++ // protocol handler.
++
++ rv = CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"moz-gio",
++ result);
++ if (NS_SUCCEEDED(rv)) {
++ nsCAutoString spec(scheme);
++ spec.Append(':');
++
++ nsIURI *uri;
++ rv = (*result)->NewURI(spec, nsnull, nsnull, &uri);
++ if (NS_SUCCEEDED(rv)) {
++ NS_RELEASE(uri);
++ return rv;
++ }
++
++ NS_RELEASE(*result);
++ }
++
+ // check to see whether GnomeVFS can handle this URI scheme. if it can
+ // create a nsIURI for the "scheme:", then we assume it has support for
+ // the requested protocol. otherwise, we failover to using the default
diff --git a/staging/xulrunner/xulrunner-omnijar.patch b/staging/xulrunner/xulrunner-omnijar.patch
new file mode 100644
index 000000000..66ec5206c
--- /dev/null
+++ b/staging/xulrunner/xulrunner-omnijar.patch
@@ -0,0 +1,1737 @@
+# HG changeset patch
+# Parent a7dea879b4b445a23186f438900562155bb39e99
+Bug 620931 part 1 - Use chrome manifest to register resource://gre-resources/
+
+diff --git a/layout/style/jar.mn b/layout/style/jar.mn
+--- a/layout/style/jar.mn
++++ b/layout/style/jar.mn
+@@ -1,8 +1,10 @@
+ toolkit.jar:
+ * res/ua.css (ua.css)
+ res/html.css (html.css)
+ res/quirk.css (quirk.css)
+ res/viewsource.css (viewsource.css)
+ * res/forms.css (forms.css)
+ res/arrow.gif (arrow.gif)
+ res/arrowd.gif (arrowd.gif)
++
++% resource gre-resources %res/
+diff --git a/netwerk/protocol/res/nsResProtocolHandler.cpp b/netwerk/protocol/res/nsResProtocolHandler.cpp
+--- a/netwerk/protocol/res/nsResProtocolHandler.cpp
++++ b/netwerk/protocol/res/nsResProtocolHandler.cpp
+@@ -75,17 +75,16 @@ static nsResProtocolHandler *gResHandler
+ //
+ // this enables PR_LOG_ALWAYS level information and places all output in
+ // the file log.txt
+ //
+ static PRLogModuleInfo *gResLog;
+ #endif
+
+ #define kGRE NS_LITERAL_CSTRING("gre")
+-#define kGRE_RESOURCES NS_LITERAL_CSTRING("gre-resources")
+
+ //----------------------------------------------------------------------------
+ // nsResURL : overrides nsStandardURL::GetFile to provide nsIFile resolution
+ //----------------------------------------------------------------------------
+
+ nsresult
+ nsResURL::EnsureFile()
+ {
+@@ -197,28 +196,16 @@ nsResProtocolHandler::Init()
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ //
+ // make resource://gre/ point to the GRE directory
+ //
+ rv = AddSpecialDir(NS_GRE_DIR, kGRE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+- // make resource://gre-resources/ point to gre toolkit[.jar]/res
+- nsCOMPtr<nsIURI> greURI;
+- nsCOMPtr<nsIURI> greResURI;
+- GetSubstitution(kGRE, getter_AddRefs(greURI));
+-#ifdef MOZ_CHROME_FILE_FORMAT_JAR
+- NS_NAMED_LITERAL_CSTRING(strGRE_RES_URL, "jar:chrome/toolkit.jar!/res/");
+-#else
+- NS_NAMED_LITERAL_CSTRING(strGRE_RES_URL, "chrome/toolkit/res/");
+-#endif
+- rv = mIOService->NewURI(strGRE_RES_URL, nsnull, greURI,
+- getter_AddRefs(greResURI));
+- SetSubstitution(kGRE_RESOURCES, greResURI);
+ //XXXbsmedberg Neil wants a resource://pchrome/ for the profile chrome dir...
+ // but once I finish multiple chrome registration I'm not sure that it is needed
+
+ // XXX dveditz: resource://pchrome/ defeats profile directory salting
+ // if web content can load it. Tread carefully.
+
+ return rv;
+ }
+@@ -242,22 +229,16 @@ nsResProtocolHandler::Init(nsIFile *aOmn
+ // these entries should be kept in sync with the normal Init function
+
+ // resource:/// points to jar:omni.jar!/
+ SetSubstitution(EmptyCString(), uri);
+
+ // resource://gre/ points to jar:omni.jar!/
+ SetSubstitution(kGRE, uri);
+
+- urlStr += "chrome/toolkit/res/";
+- rv = mIOService->NewURI(urlStr, nsnull, nsnull, getter_AddRefs(uri));
+- NS_ENSURE_SUCCESS(rv, rv);
+-
+- // resource://gre-resources/ points to jar:omni.jar!/chrome/toolkit/res/
+- SetSubstitution(kGRE_RESOURCES, uri);
+ return NS_OK;
+ }
+ #endif
+
+ #ifdef MOZ_IPC
+ static PLDHashOperator
+ EnumerateSubstitution(const nsACString& aKey,
+ nsIURI* aURI,
+# HG changeset patch
+# Parent 3038cccba1a071d6b418e15442d0f2d9f3dcb11d
+Bug 620931 part 2 - When building --with-libxul-sdk, use the right preferences directory
+
+diff --git a/browser/locales/Makefile.in b/browser/locales/Makefile.in
+--- a/browser/locales/Makefile.in
++++ b/browser/locales/Makefile.in
+@@ -183,17 +183,17 @@ install:: $(addsuffix .xml,$(SEARCH_PLUG
+ $(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/searchplugins
+
+
+ libs-%:
+ $(NSINSTALL) -D $(DIST)/install
+ @$(MAKE) -C ../../toolkit/locales libs-$* BOTH_MANIFESTS=1
+ @$(MAKE) -C ../../services/sync/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
+ @$(MAKE) -C ../../extensions/spellcheck/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
+- @$(MAKE) libs AB_CD=$* XPI_NAME=locale-$* PREF_DIR=defaults/pref BOTH_MANIFESTS=1
++ @$(MAKE) libs AB_CD=$* XPI_NAME=locale-$* PREF_DIR=$(PREF_DIR) BOTH_MANIFESTS=1
+ @$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
+
+
+ repackage-win32-installer: WIN32_INSTALLER_OUT="$(_ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe"
+ repackage-win32-installer: $(WIN32_INSTALLER_IN) $(SUBMAKEFILES)
+ @echo "Repackaging $(WIN32_INSTALLER_IN) into $(WIN32_INSTALLER_OUT)."
+ $(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY) export
+ $(MAKE) -C ../installer/windows CONFIG_DIR=l10ngen l10ngen/setup.exe l10ngen/7zSD.sfx
+diff --git a/toolkit/mozapps/installer/packager.mk b/toolkit/mozapps/installer/packager.mk
+--- a/toolkit/mozapps/installer/packager.mk
++++ b/toolkit/mozapps/installer/packager.mk
+@@ -307,17 +307,17 @@ OMNIJAR_FILES = \
+ res \
+ defaults \
+ greprefs.js \
+ jsloader \
+ $(NULL)
+
+ NON_OMNIJAR_FILES += \
+ chrome/icons/\* \
+- defaults/pref/channel-prefs.js \
++ $(PREF_DIR)/channel-prefs.js \
+ res/cursors/\* \
+ res/MainMenu.nib/\* \
+ $(NULL)
+
+ PACK_OMNIJAR = \
+ rm -f omni.jar components/binary.manifest && \
+ grep -h '^binary-component' components/*.manifest > binary.manifest ; \
+ sed -e 's/^binary-component/\#binary-component/' components/components.manifest > components.manifest && \
+# HG changeset patch
+# Parent cd8df8030f7ad7530692bd7c4391a8009df56a02
+Bug 620931 part 3 - Allow GRE and XUL application to use omni.jar independently
+
+We now store two independent locations for an omni.jar, allowing GRE/XRE and
+XUL application to each have their own omni.jar. And since xulrunner setups
+are very independent from the XUL applications, we implement support for both
+omni.jar and non omni.jar cases in the same runtime, with the side effect of
+allowing to switch from one to the other manually without rebuilding the
+binaries.
+
+We let the mozilla::Omnijar API handle both cases, so that callers don't need
+too much work to support them.
+
+We also make the preferences service load the same set of preferences in all
+the various cases (unified vs. separate, omni.jar vs. no omni.jar).
+
+The child process launcher for IPC is modified to pass the base directories
+needed for the mozilla::Omnijar API initialization in the child process.
+
+Finally, the startupcache file name canonicalization is modified to separate
+APP and GRE resources.
+
+diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp
+--- a/ipc/glue/GeckoChildProcessHost.cpp
++++ b/ipc/glue/GeckoChildProcessHost.cpp
+@@ -440,26 +440,29 @@ GeckoChildProcessHost::PerformAsyncLaunc
+ // other end of the socketpair() from us
+
+ std::vector<std::string> childArgv;
+
+ childArgv.push_back(exePath.value());
+
+ childArgv.insert(childArgv.end(), aExtraOpts.begin(), aExtraOpts.end());
+
+-#ifdef MOZ_OMNIJAR
+ // Make sure the child process can find the omnijar
+ // See XRE_InitCommandLine in nsAppRunner.cpp
+- nsCAutoString omnijarPath;
+- if (mozilla::OmnijarPath()) {
+- mozilla::OmnijarPath()->GetNativePath(omnijarPath);
+- childArgv.push_back("-omnijar");
+- childArgv.push_back(omnijarPath.get());
++ nsCAutoString path;
++ nsCOMPtr<nsIFile> file = mozilla::Omnijar::GetBase(mozilla::Omnijar::GRE);
++ if (file && NS_SUCCEEDED(file->GetNativePath(path))) {
++ childArgv.push_back("-grebase");
++ childArgv.push_back(path.get());
+ }
+-#endif
++ file = mozilla::Omnijar::GetBase(mozilla::Omnijar::APP);
++ if (file && NS_SUCCEEDED(file->GetNativePath(path))) {
++ childArgv.push_back("-appbase");
++ childArgv.push_back(path.get());
++ }
+
+ childArgv.push_back(pidstring);
+
+ #if defined(MOZ_CRASHREPORTER)
+ # if defined(OS_LINUX)
+ int childCrashFd, childCrashRemapFd;
+ if (!CrashReporter::CreateNotificationPipeForChild(
+ &childCrashFd, &childCrashRemapFd))
+@@ -552,26 +555,29 @@ GeckoChildProcessHost::PerformAsyncLaunc
+ for (std::vector<std::string>::iterator it = aExtraOpts.begin();
+ it != aExtraOpts.end();
+ ++it) {
+ cmdLine.AppendLooseValue(UTF8ToWide(*it));
+ }
+
+ cmdLine.AppendLooseValue(std::wstring(mGroupId.get()));
+
+-#ifdef MOZ_OMNIJAR
+ // Make sure the child process can find the omnijar
+ // See XRE_InitCommandLine in nsAppRunner.cpp
+- nsAutoString omnijarPath;
+- if (mozilla::OmnijarPath()) {
+- mozilla::OmnijarPath()->GetPath(omnijarPath);
+- cmdLine.AppendLooseValue(UTF8ToWide("-omnijar"));
+- cmdLine.AppendLooseValue(omnijarPath.get());
++ nsAutoString path;
++ nsCOMPtr<nsIFile> file = mozilla::Omnijar::GetBase(mozilla::Omnijar::GRE);
++ if (file && NS_SUCCEEDED(file->GetPath(path))) {
++ cmdLine.AppendLooseValue(UTF8ToWide("-grebase"));
++ cmdLine.AppendLooseValue(path.get());
+ }
+-#endif
++ file = mozilla::Omnijar::GetBase(mozilla::Omnijar::APP);
++ if (file && NS_SUCCEEDED(file->GetPath(path))) {
++ cmdLine.AppendLooseValue(UTF8ToWide("-appbase"));
++ cmdLine.AppendLooseValue(path.get());
++ }
+
+ cmdLine.AppendLooseValue(UTF8ToWide(pidstring));
+
+ #if defined(MOZ_CRASHREPORTER)
+ cmdLine.AppendLooseValue(
+ UTF8ToWide(CrashReporter::GetChildNotificationPipe()));
+ #endif
+
+diff --git a/js/src/xpconnect/loader/mozJSComponentLoader.cpp b/js/src/xpconnect/loader/mozJSComponentLoader.cpp
+--- a/js/src/xpconnect/loader/mozJSComponentLoader.cpp
++++ b/js/src/xpconnect/loader/mozJSComponentLoader.cpp
+@@ -81,16 +81,17 @@
+ #include "nsIConsoleService.h"
+ #include "nsIStorageStream.h"
+ #include "nsIStringStream.h"
+ #include "prmem.h"
+ #if defined(XP_WIN)
+ #include "nsILocalFileWin.h"
+ #endif
+ #include "xpcprivate.h"
++#include "nsIResProtocolHandler.h"
+
+ #ifdef MOZ_ENABLE_LIBXUL
+ #include "mozilla/scache/StartupCache.h"
+ #include "mozilla/scache/StartupCacheUtils.h"
+ #endif
+ #include "mozilla/Omnijar.h"
+
+ #include "jsdbgapi.h"
+@@ -621,34 +622,21 @@ mozJSComponentLoader::LoadModule(nsILoca
+
+ const mozilla::Module*
+ mozJSComponentLoader::LoadModuleFromJAR(nsILocalFile *aJarFile,
+ const nsACString &aComponentPath)
+ {
+ #if !defined(XPCONNECT_STANDALONE)
+ nsresult rv;
+
+- nsCAutoString fullSpec;
+-
+-#ifdef MOZ_OMNIJAR
+- PRBool equal;
+- rv = aJarFile->Equals(mozilla::OmnijarPath(), &equal);
+- if (NS_SUCCEEDED(rv) && equal) {
+- fullSpec = "resource://gre/";
+- } else {
+-#endif
+- nsCAutoString fileSpec;
+- NS_GetURLSpecFromActualFile(aJarFile, fileSpec);
+- fullSpec = "jar:";
+- fullSpec += fileSpec;
+- fullSpec += "!/";
+-#ifdef MOZ_OMNIJAR
+- }
+-#endif
+-
++ nsCAutoString fullSpec, fileSpec;
++ NS_GetURLSpecFromActualFile(aJarFile, fileSpec);
++ fullSpec = "jar:";
++ fullSpec += fileSpec;
++ fullSpec += "!/";
+ fullSpec += aComponentPath;
+
+ nsCOMPtr<nsIURI> uri;
+ rv = NS_NewURI(getter_AddRefs(uri), fullSpec);
+ if (NS_FAILED(rv))
+ return NULL;
+
+ nsAutoString hashstring;
+@@ -833,57 +821,138 @@ class JSScriptHolder
+ JSScriptHolder(JSContext *cx, JSScript *script)
+ : mCx(cx), mScript(script) {}
+ ~JSScriptHolder() { ::JS_DestroyScript(mCx, mScript); }
+ private:
+ JSContext *mCx;
+ JSScript *mScript;
+ };
+
++static const char baseName[2][5] = { "gre/", "app/" };
++
++static inline PRBool
++canonicalizeBase(nsCAutoString &spec, nsACString &out, mozilla::Omnijar::Type aType)
++{
++ nsCAutoString base;
++ nsresult rv = mozilla::Omnijar::GetURIString(aType, base);
++
++ if (NS_FAILED(rv) || !base.Length())
++ return PR_FALSE;
++
++ if (base.Compare(spec.get(), PR_FALSE, base.Length()))
++ return PR_FALSE;
++
++ out.Append("/resource/");
++ out.Append(baseName[aType]);
++ out.Append(Substring(spec, base.Length()));
++ return PR_TRUE;
++}
+ /**
+ * PathifyURI transforms mozilla .js uris into useful zip paths
+ * to make it makes it easier to manipulate startup cache entries
+ * using standard zip tools.
+ * Transformations applied:
+- * * jsloader/<scheme> prefix is used to group mozJSComponentLoader cache entries in
++ * * jsloader/ prefix is used to group mozJSComponentLoader cache entries in
+ * a top-level zip directory.
+- * * In MOZ_OMNIJAR case resource:/// and resource://gre/ URIs refer to the same path
+- * so treat both of them as resource://gre/
++ * * resource:// URIs are resolved to their corresponding file/jar URI to
++ * canonicalize resources URIs other than gre and app.
++ * * Paths under GRE or APP directory have their base path replaced with
++ * resource/gre or resource/app to avoid depending on install location.
++ * * jar:file:///path/to/file.jar!/sub/path urls are replaced with
++ * /path/to/file.jar/sub/path
+ * * .bin suffix is added to the end of the path to indicate that jsloader/ entries
+ * are binary representations of JS source.
+ * For example:
+- * resource://gre/modules/XPCOMUtils.jsm becomes
+- * jsloader/resource/gre/modules/XPCOMUtils.jsm.bin
++ * resource://gre/modules/XPCOMUtils.jsm or
++ * file://$GRE_DIR/modules/XPCOMUtils.jsm or
++ * jar:file://$GRE_DIR/omni.jar!/modules/XPCOMUtils.jsm become
++ * jsloader/resource/gre/modules/XPCOMUtils.jsm.bin
++ * file://$PROFILE_DIR/extensions/{uuid}/components/component.js becomes
++ * jsloader/$PROFILE_DIR/extensions/%7Buuid%7D/components/component.js.bin
++ * jar:file://$PROFILE_DIR/extensions/some.xpi!/components/component.js becomes
++ * jsloader/$PROFILE_DIR/extensions/some.xpi/components/component.js.bin
+ */
+ static nsresult
+ PathifyURI(nsIURI *in, nsACString &out)
+ {
+- out = "jsloader/";
+- nsCAutoString scheme;
+- nsresult rv = in->GetScheme(scheme);
+- NS_ENSURE_SUCCESS(rv, rv);
+- out.Append(scheme);
+- nsCAutoString host;
+- // OK for GetHost to fail since it's not implemented sometimes
+- in->GetHost(host);
+-#ifdef MOZ_OMNIJAR
+- if (scheme.Equals("resource") && host.Length() == 0){
+- host = "gre";
+- }
+-#endif
+- if (host.Length()) {
+- out.Append("/");
+- out.Append(host);
+- }
+- nsCAutoString path;
+- rv = in->GetPath(path);
+- NS_ENSURE_SUCCESS(rv, rv);
+- out.Append(path);
+- out.Append(".bin");
+- return NS_OK;
++ PRBool equals;
++ nsresult rv;
++ nsCOMPtr<nsIURI> uri = in;
++ nsCAutoString spec;
++
++ out = "jsloader";
++
++ // Resolve resource:// URIs. At the end of this if/else block, we
++ // have both spec and uri variables identifying the same URI.
++ if (NS_SUCCEEDED(in->SchemeIs("resource", &equals)) && equals) {
++ nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ nsCOMPtr<nsIProtocolHandler> ph;
++ rv = ioService->GetProtocolHandler("resource", getter_AddRefs(ph));
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ nsCOMPtr<nsIResProtocolHandler> irph(do_QueryInterface(ph, &rv));
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ rv = irph->ResolveURI(in, spec);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ rv = ioService->NewURI(spec, nsnull, nsnull, getter_AddRefs(uri));
++ NS_ENSURE_SUCCESS(rv, rv);
++ } else {
++ rv = in->GetSpec(spec);
++ NS_ENSURE_SUCCESS(rv, rv);
++ }
++
++ if (!canonicalizeBase(spec, out, mozilla::Omnijar::GRE) &&
++ !canonicalizeBase(spec, out, mozilla::Omnijar::APP)) {
++ if (NS_SUCCEEDED(uri->SchemeIs("file", &equals)) && equals) {
++ nsCOMPtr<nsIFileURL> baseFileURL;
++ baseFileURL = do_QueryInterface(uri, &rv);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ nsCAutoString path;
++ rv = baseFileURL->GetPath(path);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ out.Append(path);
++ } else if (NS_SUCCEEDED(uri->SchemeIs("jar", &equals)) && equals) {
++ nsCOMPtr<nsIJARURI> jarURI = do_QueryInterface(uri, &rv);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ nsCOMPtr<nsIURI> jarFileURI;
++ rv = jarURI->GetJARFile(getter_AddRefs(jarFileURI));
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ nsCOMPtr<nsIFileURL> jarFileURL;
++ jarFileURL = do_QueryInterface(jarFileURI, &rv);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ nsCAutoString path;
++ rv = jarFileURL->GetPath(path);
++ NS_ENSURE_SUCCESS(rv, rv);
++ out.Append(path);
++
++ rv = jarURI->GetJAREntry(path);
++ NS_ENSURE_SUCCESS(rv, rv);
++ out.Append("/");
++ out.Append(path);
++ } else { // Very unlikely
++ nsCAutoString spec;
++ rv = uri->GetSpec(spec);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ out.Append("/");
++ out.Append(spec);
++ }
++ }
++
++ out.Append(".bin");
++ return NS_OK;
+ }
+
+ /* static */
+ #ifdef MOZ_ENABLE_LIBXUL
+ nsresult
+ mozJSComponentLoader::ReadScript(StartupCache* cache, nsIURI *uri,
+ JSContext *cx, JSScript **script)
+ {
+diff --git a/modules/libjar/nsJAR.cpp b/modules/libjar/nsJAR.cpp
+--- a/modules/libjar/nsJAR.cpp
++++ b/modules/libjar/nsJAR.cpp
+@@ -171,26 +171,23 @@ nsJAR::Open(nsIFile* zipFile)
+ if (mLock) return NS_ERROR_FAILURE; // Already open!
+
+ mZipFile = zipFile;
+ mOuterZipEntry.Truncate();
+
+ mLock = PR_NewLock();
+ NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY);
+
+-#ifdef MOZ_OMNIJAR
+ // The omnijar is special, it is opened early on and closed late
+ // this avoids reopening it
+- PRBool equals;
+- nsresult rv = zipFile->Equals(mozilla::OmnijarPath(), &equals);
+- if (NS_SUCCEEDED(rv) && equals) {
+- mZip = mozilla::OmnijarReader();
++ nsZipArchive *zip = mozilla::Omnijar::GetReader(zipFile);
++ if (zip) {
++ mZip = zip;
+ return NS_OK;
+ }
+-#endif
+ return mZip->OpenArchive(zipFile);
+ }
+
+ NS_IMETHODIMP
+ nsJAR::OpenInner(nsIZipReader *aZipReader, const char *aZipEntry)
+ {
+ NS_ENSURE_ARG_POINTER(aZipReader);
+ NS_ENSURE_ARG_POINTER(aZipEntry);
+@@ -234,23 +231,22 @@ nsJAR::Close()
+ mLock = nsnull;
+ }
+
+ mParsedManifest = PR_FALSE;
+ mManifestData.Reset();
+ mGlobalStatus = JAR_MANIFEST_NOT_PARSED;
+ mTotalItemsInManifest = 0;
+
+-#ifdef MOZ_OMNIJAR
+- if (mZip == mozilla::OmnijarReader()) {
++ if ((mZip == mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE)) ||
++ (mZip == mozilla::Omnijar::GetReader(mozilla::Omnijar::APP))) {
+ mZip.forget();
+ mZip = new nsZipArchive();
+ return NS_OK;
+ }
+-#endif
+ return mZip->CloseArchive();
+ }
+
+ NS_IMETHODIMP
+ nsJAR::Test(const char *aEntryName)
+ {
+ return mZip->Test(aEntryName);
+ }
+@@ -391,22 +387,21 @@ nsJAR::GetInputStreamWithSpec(const nsAC
+ NS_IMETHODIMP
+ nsJAR::GetCertificatePrincipal(const char* aFilename, nsIPrincipal** aPrincipal)
+ {
+ //-- Parameter check
+ if (!aPrincipal)
+ return NS_ERROR_NULL_POINTER;
+ *aPrincipal = nsnull;
+
+-#ifdef MOZ_OMNIJAR
+ // Don't check signatures in the omnijar - this is only
+ // interesting for extensions/XPIs.
+- if (mZip == mozilla::OmnijarReader())
++ if ((mZip == mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE)) ||
++ (mZip == mozilla::Omnijar::GetReader(mozilla::Omnijar::APP)))
+ return NS_OK;
+-#endif
+
+ //-- Parse the manifest
+ nsresult rv = ParseManifest();
+ if (NS_FAILED(rv)) return rv;
+ if (mGlobalStatus == JAR_NO_MANIFEST)
+ return NS_OK;
+
+ PRInt16 requestedStatus;
+diff --git a/modules/libpref/src/nsPrefService.cpp b/modules/libpref/src/nsPrefService.cpp
+--- a/modules/libpref/src/nsPrefService.cpp
++++ b/modules/libpref/src/nsPrefService.cpp
+@@ -67,20 +67,18 @@
+
+ #include "prefapi.h"
+ #include "prefread.h"
+ #include "prefapi_private_data.h"
+ #include "PrefTuple.h"
+
+ #include "nsITimelineService.h"
+
+-#ifdef MOZ_OMNIJAR
+ #include "mozilla/Omnijar.h"
+ #include "nsZipArchive.h"
+-#endif
+
+ // Definitions
+ #define INITIAL_PREF_FILES 10
+ static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
+
+ // Prototypes
+ static nsresult openPrefFile(nsIFile* aFile);
+ static nsresult pref_InitInitialObjects(void);
+@@ -793,124 +791,144 @@ static nsresult pref_LoadPrefsInDirList(
+ pref_LoadPrefsInDir(dir, nsnull, 0);
+ }
+ }
+ }
+ }
+ return NS_OK;
+ }
+
+-//----------------------------------------------------------------------------------------
+-// Initialize default preference JavaScript buffers from
+-// appropriate TEXT resources
+-//----------------------------------------------------------------------------------------
+-static nsresult pref_InitDefaults()
+-{
+- nsCOMPtr<nsIFile> greprefsFile;
+- nsresult rv;
+-
+- rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greprefsFile));
+- NS_ENSURE_SUCCESS(rv, rv);
+-
+- rv = greprefsFile->AppendNative(NS_LITERAL_CSTRING("greprefs.js"));
+- NS_ENSURE_SUCCESS(rv, rv);
+-
+- rv = openPrefFile(greprefsFile);
+- if (NS_FAILED(rv)) {
+- NS_WARNING("Error parsing GRE default preferences. Is this an old-style embedding app?");
+- }
+-
+- return NS_OK;
+-}
+-
+-#ifdef MOZ_OMNIJAR
+ static nsresult pref_ReadPrefFromJar(nsZipArchive* jarReader, const char *name)
+ {
+ nsZipItemPtr<char> manifest(jarReader, name, true);
+ NS_ENSURE_TRUE(manifest.Buffer(), NS_ERROR_NOT_AVAILABLE);
+
+ PrefParseState ps;
+ PREF_InitParseState(&ps, PREF_ReaderCallback, NULL);
+ nsresult rv = PREF_ParseBuf(&ps, manifest, manifest.Length());
+ PREF_FinalizeParseState(&ps);
+
+ return rv;
+ }
+
+-static nsresult pref_InitAppDefaultsFromOmnijar()
+-{
+- nsresult rv;
+-
+- nsZipArchive* jarReader = mozilla::OmnijarReader();
+- if (!jarReader)
+- return pref_InitDefaults();
+-
+- rv = pref_ReadPrefFromJar(jarReader, "greprefs.js");
+- NS_ENSURE_SUCCESS(rv, rv);
+-
+- nsZipFind *findPtr;
+- rv = jarReader->FindInit("defaults/pref/*.js$", &findPtr);
+- NS_ENSURE_SUCCESS(rv, rv);
+-
+- nsAutoPtr<nsZipFind> find(findPtr);
+-
+- nsTArray<nsCString> prefEntries;
+- const char *entryName;
+- PRUint16 entryNameLen;
+- while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
+- prefEntries.AppendElement(Substring(entryName, entryName + entryNameLen));
+- }
+-
+- prefEntries.Sort();
+- for (PRUint32 i = prefEntries.Length(); i--; ) {
+- rv = pref_ReadPrefFromJar(jarReader, prefEntries[i].get());
+- if (NS_FAILED(rv))
+- NS_WARNING("Error parsing preferences.");
+- }
+-
+- return NS_OK;
+-}
+-#endif
+-
++//----------------------------------------------------------------------------------------
++// Initialize default preference JavaScript buffers from
++// appropriate TEXT resources
++//----------------------------------------------------------------------------------------
+ static nsresult pref_InitInitialObjects()
+ {
+ nsresult rv;
+
+- // first we parse the GRE default prefs. This also works if we're not using a GRE,
+-#ifdef MOZ_OMNIJAR
+- rv = pref_InitAppDefaultsFromOmnijar();
+-#else
+- rv = pref_InitDefaults();
+-#endif
+- NS_ENSURE_SUCCESS(rv, rv);
++ // In omni.jar case, we load the following prefs:
++ // - jar:$gre/omni.jar!/greprefs.js
++ // - jar:$gre/omni.jar!/defaults/pref/*.js
++ // In non omni.jar case, we load:
++ // - $gre/greprefs.js
++ //
++ // When $app == $gre, we additionally load, in all cases:
++ // - $gre/defaults/pref/*.js
++ // This is kept for bug 591866 (channel-prefs.js should not be in omni.jar).
++ // We load all files instead of channel-prefs.js only to have the same
++ // behaviour as $app != $gre.
++ //
++ // When $app != $gre, we additionally load, in omni.jar case:
++ // - jar:$app/omni.jar!/defaults/preferences/*.js
++ // - $app/defaults/preferences/*.js
++ // and in non omni.jar case:
++ // - $app/defaults/preferences/*.js
+
+- nsCOMPtr<nsIFile> defaultPrefDir;
+- // now parse the "application" default preferences
+- rv = NS_GetSpecialDirectory(NS_APP_PREF_DEFAULTS_50_DIR, getter_AddRefs(defaultPrefDir));
+- NS_ENSURE_SUCCESS(rv, rv);
++ nsZipFind *findPtr;
++ nsAutoPtr<nsZipFind> find;
++ nsTArray<nsCString> prefEntries;
++ const char *entryName;
++ PRUint16 entryNameLen;
+
+- /* these pref file names should not be used: we process them after all other application pref files for backwards compatibility */
+- static const char* specialFiles[] = {
++ nsZipArchive* jarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
++ if (jarReader) {
++ // Load jar:$gre/omni.jar!/greprefs.js
++ rv = pref_ReadPrefFromJar(jarReader, "greprefs.js");
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ // Load jar:$gre/omni.jar!/defaults/pref/*.js
++ rv = jarReader->FindInit("defaults/pref/*.js$", &findPtr);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ find = findPtr;
++ while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
++ prefEntries.AppendElement(Substring(entryName, entryName + entryNameLen));
++ }
++
++ prefEntries.Sort();
++ for (PRUint32 i = prefEntries.Length(); i--; ) {
++ rv = pref_ReadPrefFromJar(jarReader, prefEntries[i].get());
++ if (NS_FAILED(rv))
++ NS_WARNING("Error parsing preferences.");
++ }
++ } else {
++ // Load $gre/greprefs.js
++ nsCOMPtr<nsIFile> greprefsFile;
++ rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greprefsFile));
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ rv = greprefsFile->AppendNative(NS_LITERAL_CSTRING("greprefs.js"));
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ rv = openPrefFile(greprefsFile);
++ if (NS_FAILED(rv))
++ NS_WARNING("Error parsing GRE default preferences. Is this an old-style embedding app?");
++ }
++
++ if (!mozilla::Omnijar::HasOmnijar(mozilla::Omnijar::APP)) {
++ // Load $gre/defaults/pref/*.js
++ nsCOMPtr<nsIFile> defaultPrefDir;
++
++ rv = NS_GetSpecialDirectory(NS_APP_PREF_DEFAULTS_50_DIR, getter_AddRefs(defaultPrefDir));
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ /* these pref file names should not be used: we process them after all other application pref files for backwards compatibility */
++ static const char* specialFiles[] = {
+ #if defined(XP_MAC) || defined(XP_MACOSX)
+ "macprefs.js"
+ #elif defined(XP_WIN)
+ "winpref.js"
+ #elif defined(XP_UNIX)
+ "unix.js"
+-#if defined(_AIX)
++#if defined(VMS)
++ , "openvms.js"
++#elif defined(_AIX)
+ , "aix.js"
+ #endif
+ #elif defined(XP_OS2)
+ "os2pref.js"
++#elif defined(XP_BEOS)
++ "beos.js"
+ #endif
+- };
++ };
+
+- rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, NS_ARRAY_LENGTH(specialFiles));
+- if (NS_FAILED(rv)) {
+- NS_WARNING("Error parsing application default preferences.");
++ rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, NS_ARRAY_LENGTH(specialFiles));
++ if (NS_FAILED(rv))
++ NS_WARNING("Error parsing application default preferences.");
++ }
++
++ // Load jar:$app/omni.jar!/defaults/preferences/*.js
++ nsZipArchive *appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
++ if (appJarReader) {
++ rv = appJarReader->FindInit("defaults/preferences/*.js$", &findPtr);
++ NS_ENSURE_SUCCESS(rv, rv);
++ find = findPtr;
++ prefEntries.Clear();
++ while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
++ prefEntries.AppendElement(Substring(entryName, entryName + entryNameLen));
++ }
++ prefEntries.Sort();
++ for (PRUint32 i = prefEntries.Length(); i--; ) {
++ rv = pref_ReadPrefFromJar(appJarReader, prefEntries[i].get());
++ if (NS_FAILED(rv))
++ NS_WARNING("Error parsing preferences.");
++ }
+ }
+
+ rv = pref_LoadPrefsInDirList(NS_APP_PREFS_DEFAULTS_DIR_LIST);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_CreateServicesFromCategory(NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID,
+ nsnull, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID);
+
+diff --git a/netwerk/protocol/res/nsResProtocolHandler.cpp b/netwerk/protocol/res/nsResProtocolHandler.cpp
+--- a/netwerk/protocol/res/nsResProtocolHandler.cpp
++++ b/netwerk/protocol/res/nsResProtocolHandler.cpp
+@@ -152,97 +152,62 @@ nsResProtocolHandler::nsResProtocolHandl
+ }
+
+ nsResProtocolHandler::~nsResProtocolHandler()
+ {
+ gResHandler = nsnull;
+ }
+
+ nsresult
+-nsResProtocolHandler::AddSpecialDir(const char* aSpecialDir, const nsACString& aSubstitution)
+-{
+- nsCOMPtr<nsIFile> file;
+- nsresult rv = NS_GetSpecialDirectory(aSpecialDir, getter_AddRefs(file));
+- NS_ENSURE_SUCCESS(rv, rv);
+-
+- nsCOMPtr<nsIURI> uri;
+- rv = mIOService->NewFileURI(file, getter_AddRefs(uri));
+- NS_ENSURE_SUCCESS(rv, rv);
+-
+- return SetSubstitution(aSubstitution, uri);
+-}
+-
+-nsresult
+ nsResProtocolHandler::Init()
+ {
+ if (!mSubstitutions.Init(32))
+ return NS_ERROR_UNEXPECTED;
+
+ nsresult rv;
+
+ mIOService = do_GetIOService(&rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+-#ifdef MOZ_OMNIJAR
+- nsCOMPtr<nsIFile> omniJar(mozilla::OmnijarPath());
+- if (omniJar)
+- return Init(omniJar);
+-#endif
+-
+- // these entries should be kept in sync with the omnijar Init function
++ nsCAutoString appURI, greURI;
++ rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::APP, appURI);
++ NS_ENSURE_SUCCESS(rv, rv);
++ rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::GRE, greURI);
++ NS_ENSURE_SUCCESS(rv, rv);
+
+ //
+- // make resource:/// point to the application directory
++ // make resource:/// point to the application directory or omnijar
+ //
+- rv = AddSpecialDir(NS_OS_CURRENT_PROCESS_DIR, EmptyCString());
++ nsCOMPtr<nsIURI> uri;
++ rv = NS_NewURI(getter_AddRefs(uri), appURI.Length() ? appURI : greURI);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ rv = SetSubstitution(EmptyCString(), uri);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ //
+ // make resource://gre/ point to the GRE directory
+ //
+- rv = AddSpecialDir(NS_GRE_DIR, kGRE);
++ if (appURI.Length()) { // We already have greURI in uri if appURI.Length() is 0.
++ rv = NS_NewURI(getter_AddRefs(uri), greURI);
++ NS_ENSURE_SUCCESS(rv, rv);
++ }
++
++ rv = SetSubstitution(kGRE, uri);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ //XXXbsmedberg Neil wants a resource://pchrome/ for the profile chrome dir...
+ // but once I finish multiple chrome registration I'm not sure that it is needed
+
+ // XXX dveditz: resource://pchrome/ defeats profile directory salting
+ // if web content can load it. Tread carefully.
+
+ return rv;
+ }
+
+-#ifdef MOZ_OMNIJAR
+-nsresult
+-nsResProtocolHandler::Init(nsIFile *aOmniJar)
+-{
+- nsresult rv;
+- nsCOMPtr<nsIURI> uri;
+- nsCAutoString omniJarSpec;
+- NS_GetURLSpecFromActualFile(aOmniJar, omniJarSpec, mIOService);
+-
+- nsCAutoString urlStr("jar:");
+- urlStr += omniJarSpec;
+- urlStr += "!/";
+-
+- rv = mIOService->NewURI(urlStr, nsnull, nsnull, getter_AddRefs(uri));
+- NS_ENSURE_SUCCESS(rv, rv);
+-
+- // these entries should be kept in sync with the normal Init function
+-
+- // resource:/// points to jar:omni.jar!/
+- SetSubstitution(EmptyCString(), uri);
+-
+- // resource://gre/ points to jar:omni.jar!/
+- SetSubstitution(kGRE, uri);
+-
+- return NS_OK;
+-}
+-#endif
+-
+ #ifdef MOZ_IPC
+ static PLDHashOperator
+ EnumerateSubstitution(const nsACString& aKey,
+ nsIURI* aURI,
+ void* aArg)
+ {
+ nsTArray<ResourceMapping>* resources =
+ static_cast<nsTArray<ResourceMapping>*>(aArg);
+diff --git a/startupcache/StartupCache.cpp b/startupcache/StartupCache.cpp
+--- a/startupcache/StartupCache.cpp
++++ b/startupcache/StartupCache.cpp
+@@ -237,27 +237,36 @@ StartupCache::GetBuffer(const char* id,
+ nsZipItemPtr<char> zipItem(mArchive, id, true);
+ if (zipItem) {
+ *outbuf = zipItem.Forget();
+ *length = zipItem.Length();
+ return NS_OK;
+ }
+ }
+
+-#ifdef MOZ_OMNIJAR
+- if (mozilla::OmnijarReader()) {
++ if (mozilla::Omnijar::GetReader(mozilla::Omnijar::APP)) {
+ // no need to checksum omnijarred entries
+- nsZipItemPtr<char> zipItem(mozilla::OmnijarReader(), id);
++ nsZipItemPtr<char> zipItem(mozilla::Omnijar::GetReader(mozilla::Omnijar::APP), id);
+ if (zipItem) {
+ *outbuf = zipItem.Forget();
+ *length = zipItem.Length();
+ return NS_OK;
+ }
+ }
+-#endif
++
++ if (mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE)) {
++ // no need to checksum omnijarred entries
++ nsZipItemPtr<char> zipItem(mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE), id);
++ if (zipItem) {
++ *outbuf = zipItem.Forget();
++ *length = zipItem.Length();
++ return NS_OK;
++ }
++ }
++
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ // Makes a copy of the buffer, client retains ownership of inbuf.
+ nsresult
+ StartupCache::PutBuffer(const char* id, const char* inbuf, PRUint32 len)
+ {
+ WaitOnWriteThread();
+diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
+--- a/toolkit/xre/nsAppRunner.cpp
++++ b/toolkit/xre/nsAppRunner.cpp
+@@ -3897,35 +3897,45 @@ XRE_InitCommandLine(int aArgc, char* aAr
+ CommandLine::Init(aArgc, canonArgs);
+
+ for (int i = 0; i < aArgc; ++i)
+ free(canonArgs[i]);
+ delete[] canonArgs;
+ #endif
+ #endif
+
+-#ifdef MOZ_OMNIJAR
+- const char *omnijarPath = nsnull;
+- ArgResult ar = CheckArg("omnijar", PR_FALSE, &omnijarPath);
++ const char *path = nsnull;
++ ArgResult ar = CheckArg("grebase", PR_FALSE, &path);
+ if (ar == ARG_BAD) {
+- PR_fprintf(PR_STDERR, "Error: argument -omnijar requires an omnijar path\n");
++ PR_fprintf(PR_STDERR, "Error: argument -grebase requires a path argument\n");
+ return NS_ERROR_FAILURE;
+ }
+
+- if (!omnijarPath)
++ if (!path)
+ return rv;
+
+- nsCOMPtr<nsILocalFile> omnijar;
+- rv = NS_NewNativeLocalFile(nsDependentCString(omnijarPath), PR_TRUE,
+- getter_AddRefs(omnijar));
+- if (NS_SUCCEEDED(rv))
+- mozilla::SetOmnijar(omnijar);
+-#endif
+-
+- return rv;
++ nsCOMPtr<nsILocalFile> greBase;
++ rv = XRE_GetFileFromPath(path, getter_AddRefs(greBase));
++ if (NS_FAILED(rv))
++ return rv;
++
++ ar = CheckArg("appbase", PR_FALSE, &path);
++ if (ar == ARG_BAD) {
++ PR_fprintf(PR_STDERR, "Error: argument -appbase requires a path argument\n");
++ return NS_ERROR_FAILURE;
++ }
++
++ nsCOMPtr<nsILocalFile> appBase;
++ if (path) {
++ rv = XRE_GetFileFromPath(path, getter_AddRefs(appBase));
++ if (NS_FAILED(rv))
++ return rv;
++ }
++
++ return mozilla::Omnijar::SetBase(greBase, appBase);
+ }
+
+ nsresult
+ XRE_DeinitCommandLine()
+ {
+ nsresult rv = NS_OK;
+
+ #if defined(MOZ_IPC)
+diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp
+--- a/toolkit/xre/nsEmbedFunctions.cpp
++++ b/toolkit/xre/nsEmbedFunctions.cpp
+@@ -512,19 +512,17 @@ XRE_InitChildProcess(int aArgc,
+ }
+
+ // Run the UI event loop on the main thread.
+ uiMessageLoop.MessageLoop::Run();
+
+ // Allow ProcessChild to clean up after itself before going out of
+ // scope and being deleted
+ process->CleanUp();
+-#ifdef MOZ_OMNIJAR
+- mozilla::SetOmnijar(nsnull);
+-#endif
++ mozilla::Omnijar::SetBase(nsnull, nsnull);
+ }
+ }
+
+ NS_LogTerm();
+ return XRE_DeinitCommandLine();
+ }
+
+ MessageLoop*
+diff --git a/xpcom/build/Makefile.in b/xpcom/build/Makefile.in
+--- a/xpcom/build/Makefile.in
++++ b/xpcom/build/Makefile.in
+@@ -64,28 +64,25 @@ CSRCS = \
+ $(NULL)
+
+ CPPSRCS = \
+ $(XPCOM_GLUE_SRC_LCPPSRCS) \
+ $(XPCOM_GLUENS_SRC_LCPPSRCS) \
+ nsXPComInit.cpp \
+ nsXPCOMStrings.cpp \
+ Services.cpp \
++ Omnijar.cpp \
+ $(NULL)
+
+ ifndef MOZ_ENABLE_LIBXUL
+ ifeq (,$(filter-out WINNT WINCE OS2,$(OS_ARCH)))
+ CPPSRCS += dlldeps.cpp
+ endif
+ endif
+
+-ifdef MOZ_OMNIJAR
+-CPPSRCS += Omnijar.cpp
+-endif
+-
+ SHARED_LIBRARY_LIBS = \
+ $(DEPTH)/chrome/src/$(LIB_PREFIX)chrome_s.$(LIB_SUFFIX) \
+ ../ds/$(LIB_PREFIX)xpcomds_s.$(LIB_SUFFIX) \
+ ../io/$(LIB_PREFIX)xpcomio_s.$(LIB_SUFFIX) \
+ ../components/$(LIB_PREFIX)xpcomcomponents_s.$(LIB_SUFFIX) \
+ ../threads/$(LIB_PREFIX)xpcomthreads_s.$(LIB_SUFFIX) \
+ ../proxy/src/$(LIB_PREFIX)xpcomproxy_s.$(LIB_SUFFIX) \
+ ../base/$(LIB_PREFIX)xpcombase_s.$(LIB_SUFFIX) \
+diff --git a/xpcom/build/Omnijar.cpp b/xpcom/build/Omnijar.cpp
+--- a/xpcom/build/Omnijar.cpp
++++ b/xpcom/build/Omnijar.cpp
+@@ -16,16 +16,17 @@
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Michael Wu <mwu@mozilla.com>
++ * Mike Hommey <mh@glandium.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+@@ -33,69 +34,175 @@
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+ #include "Omnijar.h"
+
+-#include "nsILocalFile.h"
+-#include "nsXULAppAPI.h"
++#include "nsIFile.h"
+ #include "nsZipArchive.h"
++#include "nsNetUtil.h"
+
+-static nsILocalFile* sOmnijarPath = nsnull;
+-static nsZipArchive* sOmnijarReader = nsnull;
++namespace mozilla {
+
+-static void
+-SetupReader()
++nsIFile *Omnijar::sPath[2] = { nsnull, nsnull };
++PRBool Omnijar::sIsOmnijar[2] = { PR_FALSE, PR_FALSE };
++
++#ifdef MOZ_ENABLE_LIBXUL
++nsZipArchive *Omnijar::sReader[2] = { nsnull, nsnull };
++#endif
++
++static already_AddRefed<nsIFile>
++ComputePath(nsIFile *aPath, PRBool &aIsOmnijar)
+ {
+- if (!sOmnijarPath) {
+- return;
++ PRBool isDir;
++ aIsOmnijar = PR_FALSE;
++ if (!aPath || NS_FAILED(aPath->IsDirectory(&isDir)) || !isDir)
++ return nsnull;
++
++ nsCOMPtr<nsIFile> path;
++#ifdef MOZ_ENABLE_LIBXUL
++ // Search for omni.jar in the given directory
++ if (!isDir || NS_FAILED(aPath->Clone(getter_AddRefs(path))))
++ return nsnull;
++
++ if (NS_FAILED(path->AppendNative(NS_LITERAL_CSTRING("omni.jar"))))
++ return nsnull;
++
++ if (NS_FAILED(path->Exists(&aIsOmnijar)))
++ return nsnull;
++#endif
++
++ if (!aIsOmnijar && NS_FAILED(aPath->Clone(getter_AddRefs(path))))
++ return nsnull;
++
++ return path.forget();
++}
++
++nsresult
++Omnijar::SetBase(nsIFile *aGrePath, nsIFile *aAppPath)
++{
++ NS_ABORT_IF_FALSE(aGrePath || !aAppPath, "Omnijar::SetBase(NULL, something) call forbidden");
++
++#ifdef MOZ_ENABLE_LIBXUL
++ if (sReader[GRE]) {
++ sReader[GRE]->CloseArchive();
++ delete sReader[GRE];
++ }
++ if (sReader[APP]) {
++ sReader[APP]->CloseArchive();
++ delete sReader[APP];
++ }
++ sReader[APP] = sReader[GRE] = nsnull;
++#endif
++
++ nsresult rv;
++ PRBool equals;
++ if (aAppPath) {
++ rv = aAppPath->Equals(aGrePath, &equals);
++ NS_ENSURE_SUCCESS(rv, rv);
++ } else {
++ equals = PR_TRUE;
+ }
+
+- nsZipArchive* zipReader = new nsZipArchive();
+- if (!zipReader) {
+- NS_IF_RELEASE(sOmnijarPath);
+- return;
++ nsCOMPtr<nsIFile> grePath = ComputePath(aGrePath, sIsOmnijar[GRE]);
++ nsCOMPtr<nsIFile> appPath = ComputePath(equals ? nsnull : aAppPath, sIsOmnijar[APP]);
++
++ NS_IF_RELEASE(sPath[GRE]);
++ sPath[GRE] = grePath;
++ NS_IF_ADDREF(sPath[GRE]);
++
++ NS_IF_RELEASE(sPath[APP]);
++ sPath[APP] = appPath;
++ NS_IF_ADDREF(sPath[APP]);
++
++ return NS_OK;
++}
++
++already_AddRefed<nsIFile>
++Omnijar::GetBase(Type aType)
++{
++ NS_ABORT_IF_FALSE(sPath[0], "Omnijar not initialized");
++
++ if (!sIsOmnijar[aType]) {
++ NS_IF_ADDREF(sPath[aType]);
++ return sPath[aType];
+ }
+
+- if (NS_FAILED(zipReader->OpenArchive(sOmnijarPath))) {
++ nsCOMPtr<nsIFile> file, path;
++ if (NS_FAILED(sPath[aType]->Clone(getter_AddRefs(file))))
++ return nsnull;
++
++ if (NS_FAILED(file->GetParent(getter_AddRefs(path))))
++ return nsnull;
++ return path.forget();
++}
++
++#ifdef MOZ_ENABLE_LIBXUL
++nsZipArchive *
++Omnijar::GetReader(Type aType)
++{
++ if (!sIsOmnijar[aType])
++ return nsnull;
++
++ if (sReader[aType])
++ return sReader[aType];
++
++ nsZipArchive* zipReader = new nsZipArchive();
++ if (!zipReader)
++ return nsnull;
++
++ if (NS_FAILED(zipReader->OpenArchive(sPath[aType]))) {
+ delete zipReader;
+- NS_IF_RELEASE(sOmnijarPath);
+- return;
++ return nsnull;
+ }
+
+- sOmnijarReader = zipReader;
++ return (sReader[aType] = zipReader);
+ }
+
+-nsILocalFile*
+-mozilla::OmnijarPath()
++nsZipArchive *
++Omnijar::GetReader(nsIFile *aPath)
+ {
+- if (!sOmnijarReader)
+- SetupReader();
++ PRBool equals;
++ nsresult rv;
+
+- return sOmnijarPath;
++ if (sIsOmnijar[GRE]) {
++ rv = sPath[GRE]->Equals(aPath, &equals);
++ if (NS_SUCCEEDED(rv) && equals)
++ return GetReader(GRE);
++ }
++ if (sIsOmnijar[APP]) {
++ rv = sPath[APP]->Equals(aPath, &equals);
++ if (NS_SUCCEEDED(rv) && equals)
++ return GetReader(APP);
++ }
++ return nsnull;
++}
++#endif
++
++nsresult
++Omnijar::GetURIString(Type aType, nsCString &result)
++{
++ NS_ABORT_IF_FALSE(sPath[0], "Omnijar not initialized");
++
++ result = "";
++
++ if ((aType == APP) && (!sPath[APP]))
++ return NS_OK;
++
++ nsCAutoString omniJarSpec;
++ nsresult rv = NS_GetURLSpecFromActualFile(sPath[aType], omniJarSpec);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ if (sIsOmnijar[aType]) {
++ result = "jar:";
++ result += omniJarSpec;
++ result += "!";
++ } else {
++ result = omniJarSpec;
++ }
++ result += "/";
++ return NS_OK;
+ }
+
+-nsZipArchive*
+-mozilla::OmnijarReader()
+-{
+- if (!sOmnijarReader)
+- SetupReader();
+-
+- return sOmnijarReader;
+-}
+-
+-void
+-mozilla::SetOmnijar(nsILocalFile* aPath)
+-{
+- NS_IF_RELEASE(sOmnijarPath);
+- if (sOmnijarReader) {
+- sOmnijarReader->CloseArchive();
+- delete sOmnijarReader;
+- sOmnijarReader = nsnull;
+- }
+-
+- sOmnijarPath = aPath;
+- NS_IF_ADDREF(sOmnijarPath);
+-}
+-
++} /* namespace mozilla */
+diff --git a/xpcom/build/Omnijar.h b/xpcom/build/Omnijar.h
+--- a/xpcom/build/Omnijar.h
++++ b/xpcom/build/Omnijar.h
+@@ -16,16 +16,17 @@
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Michael Wu <mwu@mozilla.com>
++ * Mike Hommey <mh@glandium.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+@@ -34,29 +35,137 @@
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+ #ifndef mozilla_Omnijar_h
+ #define mozilla_Omnijar_h
+
+-class nsILocalFile;
++#include "nscore.h"
++#include "nsTArray.h"
++#include "nsCOMPtr.h"
++#include "nsString.h"
++
++class nsIFile;
+ class nsZipArchive;
+-
+-#ifdef MOZ_OMNIJAR
++class nsIURI;
+
+ namespace mozilla {
+
++#ifdef MOZ_ENABLE_LIBXUL
++#define OMNIJAR_EXPORT
++#else
++#define OMNIJAR_EXPORT NS_EXPORT
++#endif
++
++class OMNIJAR_EXPORT Omnijar {
++private:
+ /**
+- * This returns the path to the omnijar.
+- * If the omnijar isn't available, this function will return null.
+- * Callers should fallback to flat packaging if null.
++ * Store an nsIFile for either a base directory when there is no omni.jar,
++ * or omni.jar itself. We can store two paths here, one for GRE
++ * (corresponding to resource://gre/) and one for APP
++ * (corresponding to resource:/// and resource://app/), but only
++ * store one when both point to the same location (unified).
+ */
+-nsILocalFile *OmnijarPath();
+-nsZipArchive *OmnijarReader();
+-void SetOmnijar(nsILocalFile* aPath);
++static nsIFile *sPath[2];
++/**
++ * Store whether the corresponding sPath is an omni.jar or a directory
++ */
++static PRBool sIsOmnijar[2];
++
++#ifdef MOZ_ENABLE_LIBXUL
++/**
++ * Cached nsZipArchives for the corresponding sPath
++ */
++static nsZipArchive *sReader[2];
++#endif
++
++public:
++enum Type {
++ GRE = 0,
++ APP = 1
++};
++
++/**
++ * Returns whether SetBase has been called at least once with
++ * a valid nsIFile
++ */
++static PRBool
++IsInitialized()
++{
++ // GRE path is always set after initialization.
++ return sPath[0] != nsnull;
++}
++
++/**
++ * Sets the base directories for GRE and APP. APP base directory
++ * may be nsnull, in case the APP and GRE directories are the same.
++ */
++static nsresult SetBase(nsIFile *aGrePath, nsIFile *aAppPath);
++
++/**
++ * Returns an nsIFile pointing to the omni.jar file for GRE or APP.
++ * Returns nsnull when there is no corresponding omni.jar.
++ * Also returns nsnull for APP in the unified case.
++ */
++static already_AddRefed<nsIFile>
++GetPath(Type aType)
++{
++ NS_ABORT_IF_FALSE(sPath[0], "Omnijar not initialized");
++
++ if (sIsOmnijar[aType]) {
++ NS_IF_ADDREF(sPath[aType]);
++ return sPath[aType];
++ }
++ return nsnull;
++}
++
++/**
++ * Returns whether GRE or APP use an omni.jar. Returns PR_False when
++ * using an omni.jar in the unified case.
++ */
++static PRBool
++HasOmnijar(Type aType)
++{
++ return sIsOmnijar[aType];
++}
++
++/**
++ * Returns the base directory for GRE or APP. In the unified case,
++ * returns nsnull for APP.
++ */
++static already_AddRefed<nsIFile> GetBase(Type aType);
++
++/**
++ * Returns a nsZipArchive pointer for the omni.jar file for GRE or
++ * APP. Returns nsnull in the same cases GetPath() would.
++ */
++#ifdef MOZ_ENABLE_LIBXUL
++static nsZipArchive *GetReader(Type aType);
++#else
++static nsZipArchive *GetReader(Type aType) { return nsnull; }
++#endif
++
++/**
++ * Returns a nsZipArchive pointer for the given path IAOI the given
++ * path is the omni.jar for either GRE or APP.
++ */
++#ifdef MOZ_ENABLE_LIBXUL
++static nsZipArchive *GetReader(nsIFile *aPath);
++#else
++static nsZipArchive *GetReader(nsIFile *aPath) { return nsnull; }
++#endif
++
++/**
++ * Returns the URI string corresponding to the omni.jar or directory
++ * for GRE or APP. i.e. jar:/path/to/omni.jar!/ for omni.jar and
++ * /path/to/base/dir/ otherwise. Returns an empty string for APP in
++ * the unified case.
++ * The returned URI is guaranteed to end with a slash.
++ */
++static nsresult GetURIString(Type aType, nsCString &result);
++
++}; /* class Omnijar */
+
+ } /* namespace mozilla */
+
+-#endif /* MOZ_OMNIJAR */
+-
+ #endif /* mozilla_Omnijar_h */
+diff --git a/xpcom/build/nsXPComInit.cpp b/xpcom/build/nsXPComInit.cpp
+--- a/xpcom/build/nsXPComInit.cpp
++++ b/xpcom/build/nsXPComInit.cpp
+@@ -462,35 +462,35 @@ NS_InitXPCOM2(nsIServiceManager* *result
+ nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
+ }
+
+ if (appFileLocationProvider) {
+ rv = nsDirectoryService::gService->RegisterProvider(appFileLocationProvider);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+-#ifdef MOZ_OMNIJAR
+ NS_TIME_FUNCTION_MARK("Next: Omnijar init");
+
+- if (!mozilla::OmnijarPath()) {
+- nsCOMPtr<nsILocalFile> omnijar;
++ if (!mozilla::Omnijar::IsInitialized()) {
++ nsCOMPtr<nsILocalFile> greDir, appDir;
+ nsCOMPtr<nsIFile> file;
+
+- rv = NS_ERROR_FAILURE;
+ nsDirectoryService::gService->Get(NS_GRE_DIR,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(file));
+- if (file)
+- rv = file->Append(NS_LITERAL_STRING("omni.jar"));
+- if (NS_SUCCEEDED(rv))
+- omnijar = do_QueryInterface(file);
+- if (NS_SUCCEEDED(rv))
+- mozilla::SetOmnijar(omnijar);
++ greDir = do_QueryInterface(file);
++
++ nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
++ NS_GET_IID(nsIFile),
++ getter_AddRefs(file));
++ appDir = do_QueryInterface(file);
++
++ rv = mozilla::Omnijar::SetBase(greDir, appDir);
++ NS_ENSURE_SUCCESS(rv, rv);
+ }
+-#endif
+
+ #ifdef MOZ_IPC
+ if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) {
+ NS_TIME_FUNCTION_MARK("Next: IPC command line init");
+
+ #ifdef OS_WIN
+ CommandLine::Init(0, nsnull);
+ #else
+@@ -769,18 +769,16 @@ ShutdownXPCOM(nsIServiceManager* servMgr
+ sCommandLineWasInitialized = false;
+ }
+ if (sExitManager) {
+ delete sExitManager;
+ sExitManager = nsnull;
+ }
+ #endif
+
+-#ifdef MOZ_OMNIJAR
+- mozilla::SetOmnijar(nsnull);
+-#endif
++ mozilla::Omnijar::SetBase(nsnull, nsnull);
+
+ NS_LogTerm();
+
+ return NS_OK;
+ }
+
+ } // namespace mozilla
+diff --git a/xpcom/components/nsComponentManager.cpp b/xpcom/components/nsComponentManager.cpp
+--- a/xpcom/components/nsComponentManager.cpp
++++ b/xpcom/components/nsComponentManager.cpp
+@@ -175,18 +175,16 @@ NS_DEFINE_CID(kCategoryManagerCID, NS_CA
+ #define COMPMGR_TIME_FUNCTION_CONTRACTID(cid) \
+ NS_TIME_FUNCTION_MIN_FMT(5, "%s (line %d) (contractid: %s)", MOZ_FUNCTION_NAME, \
+ __LINE__, (cid))
+ #else
+ #define COMPMGR_TIME_FUNCTION_CID(cid) do {} while (0)
+ #define COMPMGR_TIME_FUNCTION_CONTRACTID(cid) do {} while (0)
+ #endif
+
+-#define kOMNIJAR_PREFIX NS_LITERAL_CSTRING("resource:///")
+-
+ nsresult
+ nsGetServiceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const
+ {
+ nsresult rv;
+ nsXPIDLCString value;
+ nsCOMPtr<nsICategoryManager> catman;
+ nsComponentManagerImpl *compMgr = nsComponentManagerImpl::gComponentManager;
+ if (!compMgr) {
+@@ -390,47 +388,44 @@ nsresult nsComponentManagerImpl::Init()
+
+ nsCategoryManager::GetSingleton()->SuppressNotifications(true);
+
+ RegisterModule(&kXPCOMModule, NULL);
+
+ for (PRUint32 i = 0; i < sStaticModules->Length(); ++i)
+ RegisterModule((*sStaticModules)[i], NULL);
+
+-#ifdef MOZ_OMNIJAR
+- if (mozilla::OmnijarPath()) {
+- nsCOMPtr<nsIZipReader> omnijarReader = new nsJAR();
+- rv = omnijarReader->Open(mozilla::OmnijarPath());
+- if (NS_SUCCEEDED(rv))
+- RegisterJarManifest(omnijarReader, "chrome.manifest", false);
++ nsCOMPtr<nsIFile> appOmnijar = mozilla::Omnijar::GetPath(mozilla::Omnijar::APP);
++ if (appOmnijar) {
++ cl = sModuleLocations->InsertElementAt(1); // Insert after greDir
++ cl->type = NS_COMPONENT_LOCATION;
++ cl->location = do_QueryInterface(appOmnijar);
++ cl->jar = true;
+ }
+-#endif
++ nsCOMPtr<nsIFile> greOmnijar = mozilla::Omnijar::GetPath(mozilla::Omnijar::GRE);
++ if (greOmnijar) {
++ cl = sModuleLocations->InsertElementAt(0);
++ cl->type = NS_COMPONENT_LOCATION;
++ cl->location = do_QueryInterface(greOmnijar);
++ cl->jar = true;
++ }
+
+ for (PRUint32 i = 0; i < sModuleLocations->Length(); ++i) {
+ ComponentLocation& l = sModuleLocations->ElementAt(i);
+ if (!l.jar) {
+ RegisterManifestFile(l.type, l.location, false);
+ continue;
+ }
+
+ nsCOMPtr<nsIZipReader> reader = do_CreateInstance(kZipReaderCID, &rv);
+ rv = reader->Open(l.location);
+ if (NS_SUCCEEDED(rv))
+ RegisterJarManifest(reader, "chrome.manifest", false);
+ }
+
+-#ifdef MOZ_OMNIJAR
+- if (mozilla::OmnijarPath()) {
+- cl = sModuleLocations->InsertElementAt(0);
+- cl->type = NS_COMPONENT_LOCATION;
+- cl->location = mozilla::OmnijarPath();
+- cl->jar = true;
+- }
+-#endif
+-
+ nsCategoryManager::GetSingleton()->SuppressNotifications(false);
+
+ mStatus = NORMAL;
+
+ return NS_OK;
+ }
+
+ void
+# HG changeset patch
+# Parent ff1b810f78226d7f4010909d3cde05a57fdcf20c
+Bug 620931 part 4 - Fix resource://app/ to always point to the same as resource:///
+
+diff --git a/netwerk/protocol/res/nsResProtocolHandler.cpp b/netwerk/protocol/res/nsResProtocolHandler.cpp
+--- a/netwerk/protocol/res/nsResProtocolHandler.cpp
++++ b/netwerk/protocol/res/nsResProtocolHandler.cpp
+@@ -74,16 +74,17 @@ static nsResProtocolHandler *gResHandler
+ // set NSPR_LOG_FILE=log.txt
+ //
+ // this enables PR_LOG_ALWAYS level information and places all output in
+ // the file log.txt
+ //
+ static PRLogModuleInfo *gResLog;
+ #endif
+
++#define kAPP NS_LITERAL_CSTRING("app")
+ #define kGRE NS_LITERAL_CSTRING("gre")
+
+ //----------------------------------------------------------------------------
+ // nsResURL : overrides nsStandardURL::GetFile to provide nsIFile resolution
+ //----------------------------------------------------------------------------
+
+ nsresult
+ nsResURL::EnsureFile()
+@@ -179,16 +180,22 @@ nsResProtocolHandler::Init()
+ nsCOMPtr<nsIURI> uri;
+ rv = NS_NewURI(getter_AddRefs(uri), appURI.Length() ? appURI : greURI);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = SetSubstitution(EmptyCString(), uri);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ //
++ // make resource://app/ point to the application directory or omnijar
++ //
++ rv = SetSubstitution(kAPP, uri);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ //
+ // make resource://gre/ point to the GRE directory
+ //
+ if (appURI.Length()) { // We already have greURI in uri if appURI.Length() is 0.
+ rv = NS_NewURI(getter_AddRefs(uri), greURI);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ rv = SetSubstitution(kGRE, uri);
+diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
+--- a/toolkit/xre/nsXREDirProvider.cpp
++++ b/toolkit/xre/nsXREDirProvider.cpp
+@@ -300,19 +300,16 @@ nsXREDirProvider::GetFile(const char* aP
+ }
+ }
+ else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) {
+ nsCOMPtr<nsILocalFile> lf;
+ rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
+ if (NS_SUCCEEDED(rv))
+ file = lf;
+ }
+- else if (!strcmp(aProperty, "resource:app")) {
+- rv = GetAppDir()->Clone(getter_AddRefs(file));
+- }
+
+ else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) {
+ return mProfileDir->Clone(aFile);
+ }
+ else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
+ if (mProfileLocalDir)
+ return mProfileLocalDir->Clone(aFile);
+
+# HG changeset patch
+# Parent 7d2228db71a299afca60babff632a967d2d6c456
+Bug 620931 part 5 - Enable omni.jar by default on xulrunner
+
+diff --git a/xulrunner/confvars.sh b/xulrunner/confvars.sh
+--- a/xulrunner/confvars.sh
++++ b/xulrunner/confvars.sh
+@@ -36,15 +36,16 @@
+ #
+ # ***** END LICENSE BLOCK *****
+
+ MOZ_APP_NAME=xulrunner
+ MOZ_APP_DISPLAYNAME=XULRunner
+ MOZ_UPDATER=1
+ MOZ_XULRUNNER=1
+ MOZ_ENABLE_LIBXUL=1
++MOZ_CHROME_FILE_FORMAT=omni
+ MOZ_STATIC_BUILD_UNSUPPORTED=1
+ MOZ_APP_VERSION=$MOZILLA_VERSION
+ if test "$MOZ_STORAGE"; then
+ MOZ_PLACES=1
+ fi
+ MOZ_EXTENSIONS_DEFAULT=" gnomevfs"
+ MOZ_URL_CLASSIFIER=1
diff --git a/staging/xulrunner/xulrunner-version.patch b/staging/xulrunner/xulrunner-version.patch
new file mode 100644
index 000000000..8e81b23ea
--- /dev/null
+++ b/staging/xulrunner/xulrunner-version.patch
@@ -0,0 +1,12 @@
+diff -Nur mozilla-2.0.orig/xulrunner/installer/Makefile.in mozilla-2.0/xulrunner/installer/Makefile.in
+--- mozilla-2.0.orig/xulrunner/installer/Makefile.in 2011-03-03 14:12:04.000000000 -0800
++++ mozilla-2.0/xulrunner/installer/Makefile.in 2011-03-13 01:58:19.663360705 -0800
+@@ -44,6 +44,8 @@
+
+ include $(DEPTH)/config/autoconf.mk
+
++MOZ_APP_VERSION="2.0"
++
+ NO_PKG_FILES = \
+ xulrunner-config \
+ regchrome* \