diff options
Diffstat (limited to 'staging/xulrunner')
-rw-r--r-- | staging/xulrunner/PKGBUILD | 63 | ||||
-rw-r--r-- | staging/xulrunner/mozconfig | 56 | ||||
-rw-r--r-- | staging/xulrunner/mozilla-pkgconfig.patch | 60 | ||||
-rw-r--r-- | staging/xulrunner/port_gnomevfs_to_gio.patch | 1316 | ||||
-rw-r--r-- | staging/xulrunner/xulrunner-omnijar.patch | 1737 | ||||
-rw-r--r-- | staging/xulrunner/xulrunner-version.patch | 12 |
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, >ime); ++ ++ 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* \ |