bug 725408 - implement WebappRT launcher/shell; r=bsmedberg

This commit is contained in:
Myk Melez 2012-04-17 07:11:53 -07:00
parent 774269920f
commit 0e8cb8852d
38 changed files with 2196 additions and 72 deletions

View File

@ -40,6 +40,12 @@ probes/Makefile
extensions/Makefile extensions/Makefile
" "
if [ "$MOZ_WEBAPP_RUNTIME" ]; then
add_makefiles "
webapprt/Makefile
"
fi
if [ ! "$LIBXUL_SDK" ]; then if [ ! "$LIBXUL_SDK" ]; then
if [ "$STLPORT_SOURCES" ]; then if [ "$STLPORT_SOURCES" ]; then
add_makefiles " add_makefiles "

View File

@ -51,6 +51,10 @@ ifdef MOZ_SERVICES_SYNC
tier_app_dirs += services tier_app_dirs += services
endif endif
ifdef MOZ_WEBAPP_RUNTIME
tier_app_dirs += webapprt
endif
tier_app_dirs += browser tier_app_dirs += browser
# Never add other tier_app_dirs after browser. They won't get packaged # Never add other tier_app_dirs after browser. They won't get packaged
# properly on mac. # properly on mac.

View File

@ -24,8 +24,22 @@ category command-line-handler x-default @mozilla.org/browser/final-clh;1 applica
category command-line-validator b-browser @mozilla.org/browser/clh;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} category command-line-validator b-browser @mozilla.org/browser/clh;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
# nsBrowserGlue.js # nsBrowserGlue.js
# WebappRT doesn't need these instructions, and they don't necessarily work
# with it, but it does use a GRE directory that the GRE shares with Firefox,
# so in order to prevent the instructions from being processed for WebappRT,
# we need to restrict them to the applications that depend on them, i.e.:
#
# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
# browser: {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
#
# In theory we should do this for all these instructions, but in practice it is
# sufficient to do it for the app-startup one, and the file is simpler that way.
component {eab9012e-5f74-4cbc-b2b5-a590235513cc} nsBrowserGlue.js component {eab9012e-5f74-4cbc-b2b5-a590235513cc} nsBrowserGlue.js
contract @mozilla.org/browser/browserglue;1 {eab9012e-5f74-4cbc-b2b5-a590235513cc} contract @mozilla.org/browser/browserglue;1 {eab9012e-5f74-4cbc-b2b5-a590235513cc}
category app-startup nsBrowserGlue service,@mozilla.org/browser/browserglue;1 category app-startup nsBrowserGlue service,@mozilla.org/browser/browserglue;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}
component {d8903bf6-68d5-4e97-bcd1-e4d3012f721a} nsBrowserGlue.js component {d8903bf6-68d5-4e97-bcd1-e4d3012f721a} nsBrowserGlue.js
contract @mozilla.org/content-permission/prompt;1 {d8903bf6-68d5-4e97-bcd1-e4d3012f721a} contract @mozilla.org/content-permission/prompt;1 {d8903bf6-68d5-4e97-bcd1-e4d3012f721a}

View File

@ -1,3 +1,16 @@
# WebappRT doesn't need these instructions, and they don't necessarily work
# with it, but it does use a GRE directory that the GRE shares with Firefox,
# so in order to prevent the instructions from being processed for WebappRT,
# we need to restrict them to the applications that depend on them, i.e.:
#
# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
# browser: {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
#
# In theory we should do this for all these instructions, but in practice it is
# sufficient to do it for the app-startup one, and the file is simpler that way.
component {229fa115-9412-4d32-baf3-2fc407f76fb1} FeedConverter.js component {229fa115-9412-4d32-baf3-2fc407f76fb1} FeedConverter.js
contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1} contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.video.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1} contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.video.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
@ -13,4 +26,4 @@ contract @mozilla.org/browser/feeds/result-writer;1 {49bb6593-3aff-4eb3-a068-271
category JavaScript-global-constructor BrowserFeedWriter @mozilla.org/browser/feeds/result-writer;1 category JavaScript-global-constructor BrowserFeedWriter @mozilla.org/browser/feeds/result-writer;1
component {792a7e82-06a0-437c-af63-b2d12e808acc} WebContentConverter.js component {792a7e82-06a0-437c-af63-b2d12e808acc} WebContentConverter.js
contract @mozilla.org/embeddor.implemented/web-content-handler-registrar;1 {792a7e82-06a0-437c-af63-b2d12e808acc} contract @mozilla.org/embeddor.implemented/web-content-handler-registrar;1 {792a7e82-06a0-437c-af63-b2d12e808acc}
category app-startup WebContentConverter service,@mozilla.org/embeddor.implemented/web-content-handler-registrar;1 category app-startup WebContentConverter service,@mozilla.org/embeddor.implemented/web-content-handler-registrar;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}

View File

@ -1,4 +1,17 @@
# WebappRT doesn't need these instructions, and they don't necessarily work
# with it, but it does use a GRE directory that the GRE shares with Firefox,
# so in order to prevent the instructions from being processed for WebappRT,
# we need to restrict them to the applications that depend on them, i.e.:
#
# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
# browser: {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
#
# In theory we should do this for all these instructions, but in practice it is
# sufficient to do it for the app-startup one, and the file is simpler that way.
component {c31f4883-839b-45f6-82ad-a6a9bc5ad599} nsPrivateBrowsingService.js component {c31f4883-839b-45f6-82ad-a6a9bc5ad599} nsPrivateBrowsingService.js
contract @mozilla.org/privatebrowsing;1 {c31f4883-839b-45f6-82ad-a6a9bc5ad599} contract @mozilla.org/privatebrowsing;1 {c31f4883-839b-45f6-82ad-a6a9bc5ad599}
category command-line-handler m-privatebrowsing @mozilla.org/privatebrowsing;1 category command-line-handler m-privatebrowsing @mozilla.org/privatebrowsing;1
category app-startup nsPrivateBrowsingService service,@mozilla.org/privatebrowsing;1 category app-startup nsPrivateBrowsingService service,@mozilla.org/privatebrowsing;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}

View File

@ -1,5 +1,18 @@
# WebappRT doesn't need these instructions, and they don't necessarily work
# with it, but it does use a GRE directory that the GRE shares with Firefox,
# so in order to prevent the instructions from being processed for WebappRT,
# we need to restrict them to the applications that depend on them, i.e.:
#
# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
# browser: {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
#
# In theory we should do this for all these instructions, but in practice it is
# sufficient to do it for the app-startup one, and the file is simpler that way.
component {5280606b-2510-4fe0-97ef-9b5a22eafe6b} nsSessionStore.js component {5280606b-2510-4fe0-97ef-9b5a22eafe6b} nsSessionStore.js
contract @mozilla.org/browser/sessionstore;1 {5280606b-2510-4fe0-97ef-9b5a22eafe6b} contract @mozilla.org/browser/sessionstore;1 {5280606b-2510-4fe0-97ef-9b5a22eafe6b}
component {ec7a6c20-e081-11da-8ad9-0800200c9a66} nsSessionStartup.js component {ec7a6c20-e081-11da-8ad9-0800200c9a66} nsSessionStartup.js
contract @mozilla.org/browser/sessionstartup;1 {ec7a6c20-e081-11da-8ad9-0800200c9a66} contract @mozilla.org/browser/sessionstartup;1 {ec7a6c20-e081-11da-8ad9-0800200c9a66}
category app-startup nsSessionStartup service,@mozilla.org/browser/sessionstartup;1 category app-startup nsSessionStartup service,@mozilla.org/browser/sessionstartup;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}

View File

@ -503,6 +503,9 @@
#ifdef MOZ_SERVICES_SYNC #ifdef MOZ_SERVICES_SYNC
@BINPATH@/@PREF_DIR@/services-sync.js @BINPATH@/@PREF_DIR@/services-sync.js
#endif #endif
#ifdef MOZ_WEBAPP_RUNTIME
@BINPATH@/@PREF_DIR@/webapprt@mozilla.org/prefs.js
#endif
@BINPATH@/greprefs.js @BINPATH@/greprefs.js
@BINPATH@/defaults/autoconfig/platform.js @BINPATH@/defaults/autoconfig/platform.js
@BINPATH@/defaults/autoconfig/prefcalls.js @BINPATH@/defaults/autoconfig/prefcalls.js
@ -624,3 +627,14 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
@BINPATH@/*.xqs @BINPATH@/*.xqs
@BINPATH@/components/*.xqs @BINPATH@/components/*.xqs
#endif #endif
#ifdef MOZ_WEBAPP_RUNTIME
; [Webapp Runtime]
@BINPATH@/webapprt-stub@BIN_SUFFIX@
@BINPATH@/chrome/webapprt@JAREXT@
@BINPATH@/chrome/webapprt.manifest
@BINPATH@/components/WebappRTComponents.manifest
@BINPATH@/components/WebappRTDirectoryProvider.js
@BINPATH@/components/WebappRTCommandLineHandler.js
@BINPATH@/webapprt.ini
#endif

View File

@ -0,0 +1,49 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!-- LOCALIZATION NOTE: These are localized strings for the webapp runtime,
- which loads a webapp in a separate process from Firefox. Webapps loaded
- in this way have very little application chrome, but the runtime does
- provide them with some default functionality, like the standard OS
- menus/menuitems. -->
<!ENTITY fileMenu.label "File">
<!ENTITY fileMenu.accesskey "F">
<!ENTITY quitApplicationCmdWin.label "Exit">
<!ENTITY quitApplicationCmdWin.accesskey "x">
<!ENTITY quitApplicationCmd.label "Quit">
<!ENTITY quitApplicationCmd.accesskey "Q">
<!-- On Mac, we create the Quit and Hide command labels dynamically,
- using properties in window.properties, in order to include the name
- of the webapp in the labels without creating a DTD file for it. -->
<!ENTITY quitApplicationCmdMac.key "Q">
<!ENTITY hideThisAppCmdMac.key "H">
<!ENTITY hideOtherAppsCmdMac.label "Hide Others">
<!ENTITY hideOtherAppsCmdMac.key "H">
<!ENTITY showAllAppsCmdMac.label "Show All">
<!ENTITY editMenu.label "Edit">
<!ENTITY editMenu.accesskey "E">
<!ENTITY undoCmd.label "Undo">
<!ENTITY undoCmd.key "Z">
<!ENTITY undoCmd.accesskey "U">
<!ENTITY redoCmd.label "Redo">
<!ENTITY redoCmd.key "Y">
<!ENTITY redoCmd.accesskey "R">
<!ENTITY cutCmd.label "Cut">
<!ENTITY cutCmd.key "X">
<!ENTITY cutCmd.accesskey "t">
<!ENTITY copyCmd.label "Copy">
<!ENTITY copyCmd.key "C">
<!ENTITY copyCmd.accesskey "C">
<!ENTITY pasteCmd.label "Paste">
<!ENTITY pasteCmd.key "V">
<!ENTITY pasteCmd.accesskey "P">
<!ENTITY deleteCmd.label "Delete">
<!ENTITY deleteCmd.key "D">
<!ENTITY deleteCmd.accesskey "D">
<!ENTITY selectAllCmd.label "Select All">
<!ENTITY selectAllCmd.key "A">
<!ENTITY selectAllCmd.accesskey "A">

View File

@ -0,0 +1,17 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
# LOCALIZATION NOTE: These are localized strings for the webapp runtime,
# which loads a webapp in a separate process from Firefox. Webapps loaded
# in this way have very little application chrome, but the runtime does
# provide them with some default functionality, like the standard OS
# menus/menuitems.
# LOCALIZATION NOTE (quitApplicationCmdMac.label): %S will be replaced with
# the name of the webapp.
quitApplicationCmdMac.label=Quit %S
# LOCALIZATION NOTE (hideApplicationCmdMac.label): %S will be replaced with
# the name of the webapp.
hideApplicationCmdMac.label=Hide %S

View File

@ -110,3 +110,6 @@
% locale testpilot @AB_CD@ %locale/feedback/ % locale testpilot @AB_CD@ %locale/feedback/
locale/feedback/main.dtd (%feedback/main.dtd) locale/feedback/main.dtd (%feedback/main.dtd)
locale/feedback/main.properties (%feedback/main.properties) locale/feedback/main.properties (%feedback/main.properties)
% locale webapprt @AB_CD@ %locale/webapprt/
locale/webapprt/webapp.dtd (%webapprt/webapp.dtd)
locale/webapprt/webapp.properties (%webapprt/webapp.properties)

View File

@ -680,6 +680,8 @@ MOZ_THEME_FASTSTRIPE = @MOZ_THEME_FASTSTRIPE@
MOZ_SERVICES_SYNC = @MOZ_SERVICES_SYNC@ MOZ_SERVICES_SYNC = @MOZ_SERVICES_SYNC@
MOZ_WEBAPP_RUNTIME = @MOZ_WEBAPP_RUNTIME@
MOZ_OFFICIAL_BRANDING = @MOZ_OFFICIAL_BRANDING@ MOZ_OFFICIAL_BRANDING = @MOZ_OFFICIAL_BRANDING@
HAVE_CLOCK_MONOTONIC = @HAVE_CLOCK_MONOTONIC@ HAVE_CLOCK_MONOTONIC = @HAVE_CLOCK_MONOTONIC@

View File

@ -4497,6 +4497,7 @@ MOZ_BRANDING_DIRECTORY=
MOZ_OFFICIAL_BRANDING= MOZ_OFFICIAL_BRANDING=
MOZ_FEEDS=1 MOZ_FEEDS=1
MOZ_FLEXBOX= MOZ_FLEXBOX=
MOZ_WEBAPP_RUNTIME=
MOZ_JSDEBUGGER=1 MOZ_JSDEBUGGER=1
MOZ_AUTH_EXTENSION=1 MOZ_AUTH_EXTENSION=1
MOZ_OGG=1 MOZ_OGG=1
@ -4559,6 +4560,7 @@ MOZ_GRAPHITE=1
case "${target}" in case "${target}" in
*darwin*) *darwin*)
ACCESSIBILITY= ACCESSIBILITY=
MOZ_WEBAPP_RUNTIME=1
;; ;;
*) *)
ACCESSIBILITY=1 ACCESSIBILITY=1
@ -4569,6 +4571,7 @@ case "$target_os" in
mingw*) mingw*)
NS_ENABLE_TSF=1 NS_ENABLE_TSF=1
AC_DEFINE(NS_ENABLE_TSF) AC_DEFINE(NS_ENABLE_TSF)
MOZ_WEBAPP_RUNTIME=1
;; ;;
esac esac
@ -6274,6 +6277,44 @@ if test -n "$MOZ_TREE_FREETYPE"; then
AC_SUBST(CAIRO_FT_CFLAGS) AC_SUBST(CAIRO_FT_CFLAGS)
fi fi
dnl ========================================================
dnl Web App Runtime
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(webapp-runtime,
[ --disable-webapp-runtime Disable Web App Runtime],
MOZ_WEBAPP_RUNTIME=,
MOZ_WEBAPP_RUNTIME=1)
if test -n "$MOZ_WEBAPP_RUNTIME" -a "$OS_ARCH" = "WINNT"; then
# Disable Web App Runtime for Windows builds that use the new toolkit if the
# required major version and minimum minor version of Unicode NSIS isn't in
# the path.
REQ_NSIS_MAJOR_VER=2
MIN_NSIS_MINOR_VER=33
MOZ_PATH_PROGS(MAKENSISU, $MAKENSISU makensisu-2.46 makensisu makensis)
if test -z "$MAKENSISU" -o "$MAKENSISU" = ":"; then
AC_MSG_ERROR([To build the Web App Runtime you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path. To build without the Web App Runtime reconfigure using --disable-webapp-runtime.])
fi
changequote(,)
MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
changequote([,])
if test ! "$MAKENSISU_VER" = ""; then
MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
fi
AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
if test "$MAKENSISU_VER" = "" ||
test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
AC_MSG_RESULT([no])
AC_MSG_ERROR([To build the Web App Runtime you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path. To build without the Web App Runtime reconfigure using --disable-webapp-runtime.])
fi
AC_MSG_RESULT([yes])
fi
AC_SUBST(MOZ_WEBAPP_RUNTIME)
if test "$MOZ_WEBAPP_RUNTIME"; then
AC_DEFINE(MOZ_WEBAPP_RUNTIME)
fi
dnl ======================================================== dnl ========================================================
dnl Installer dnl Installer
dnl ======================================================== dnl ========================================================

View File

@ -12,6 +12,8 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm"); Cu.import("resource://gre/modules/FileUtils.jsm");
const WEBAPP_RUNTIME = Services.appinfo.ID == "webapprt@mozilla.org";
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() { XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
Cu.import("resource://gre/modules/NetUtil.jsm"); Cu.import("resource://gre/modules/NetUtil.jsm");
return NetUtil; return NetUtil;
@ -24,7 +26,10 @@ XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
const DIRECTORY_NAME = "webappsDir"; const DIRECTORY_NAME = "webappsDir";
#else #else
const DIRECTORY_NAME = "ProfD"; // If we're executing in the context of the webapp runtime, the data files
// are in a different directory (currently the Firefox profile that installed
// the webapp); otherwise, they're in the current profile.
const DIRECTORY_NAME = WEBAPP_RUNTIME ? "WebappRegD" : "ProfD";
#endif #endif
let DOMApplicationRegistry = { let DOMApplicationRegistry = {

View File

@ -43,6 +43,7 @@
#include "mozilla/HashFunctions.h" #include "mozilla/HashFunctions.h"
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#include "nsIXULAppInfo.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "nsAppDirectoryServiceDefs.h" #include "nsAppDirectoryServiceDefs.h"
@ -84,6 +85,8 @@ namespace mozilla {
#define INITIAL_PREF_FILES 10 #define INITIAL_PREF_FILES 10
static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID); static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
#define WEBAPPRT_APPID "webapprt@mozilla.org"
// Prototypes // Prototypes
static nsresult openPrefFile(nsIFile* aFile); static nsresult openPrefFile(nsIFile* aFile);
static nsresult pref_InitInitialObjects(void); static nsresult pref_InitInitialObjects(void);
@ -1015,6 +1018,14 @@ static nsresult pref_InitInitialObjects()
// - $app/defaults/preferences/*.js // - $app/defaults/preferences/*.js
// and in non omni.jar case: // and in non omni.jar case:
// - $app/defaults/preferences/*.js // - $app/defaults/preferences/*.js
//
// When we're running WebappRT (i.e. $app == WEBAPPRT_APPID), in omni.jar
// case, we also load:
// - jar:$gre/omni.jar!/defaults/pref/$WEBAPPRT_APPID/*.js
// This allows WebappRT-specific prefs to override those of another app
// with whom it shares an app dir (i.e. Firefox).
// (A $WEBAPPRT_APPID dir is similarly hardcoded into the app pref dir list
// in nsXREDirProvider for when we're running WebappRT in non omni.jar case.)
nsZipFind *findPtr; nsZipFind *findPtr;
nsAutoPtr<nsZipFind> find; nsAutoPtr<nsZipFind> find;
@ -1038,6 +1049,30 @@ static nsresult pref_InitInitialObjects()
} }
prefEntries.Sort(); prefEntries.Sort();
// Load jar:$gre/omni.jar!/defaults/pref/$WEBAPPRT_APPID/*.js
// if we're running WebappRT.
nsCOMPtr<nsIXULAppInfo> appInfo =
do_GetService("@mozilla.org/xre/app-info;1", &rv);
if (NS_SUCCEEDED(rv)) {
nsCAutoString appID;
if (NS_SUCCEEDED(appInfo->GetID(appID)) && appID.Equals(WEBAPPRT_APPID)) {
nsCAutoString prefsPath("defaults/pref/");
prefsPath.Append(appID);
prefsPath.AppendLiteral("/*.js$");
rv = jarReader->FindInit(prefsPath.get(), &findPtr);
NS_ENSURE_SUCCESS(rv, rv);
// Make sure the files get read last by putting them at the beginning
// of the list of pref entries (which is processed backwards), so prefs
// in these app-specific files override those in non-app-specific ones.
find = findPtr;
while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
prefEntries.InsertElementAt(0, Substring(entryName, entryNameLen));
}
}
}
for (PRUint32 i = prefEntries.Length(); i--; ) { for (PRUint32 i = prefEntries.Length(); i--; ) {
rv = pref_ReadPrefFromJar(jarReader, prefEntries[i].get()); rv = pref_ReadPrefFromJar(jarReader, prefEntries[i].get());
if (NS_FAILED(rv)) if (NS_FAILED(rv))

View File

@ -1,7 +1,20 @@
# WebappRT doesn't need these instructions, and they don't necessarily work
# with it, but it does use a GRE directory that the GRE shares with Firefox,
# so in order to prevent the instructions from being processed for WebappRT,
# we need to restrict them to the applications that depend on them, i.e.:
#
# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
# browser: {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
#
# In theory we should do this for all these instructions, but in practice it is
# sufficient to do it for the app-startup one, and the file is simpler that way.
# Weave.js # Weave.js
component {74b89fb0-f200-4ae8-a3ec-dd164117f6de} Weave.js component {74b89fb0-f200-4ae8-a3ec-dd164117f6de} Weave.js
contract @mozilla.org/weave/service;1 {74b89fb0-f200-4ae8-a3ec-dd164117f6de} contract @mozilla.org/weave/service;1 {74b89fb0-f200-4ae8-a3ec-dd164117f6de}
category app-startup WeaveService service,@mozilla.org/weave/service;1 category app-startup WeaveService service,@mozilla.org/weave/service;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}
component {d28f8a0b-95da-48f4-b712-caf37097be41} Weave.js component {d28f8a0b-95da-48f4-b712-caf37097be41} Weave.js
contract @mozilla.org/network/protocol/about;1?what=sync-log {d28f8a0b-95da-48f4-b712-caf37097be41} contract @mozilla.org/network/protocol/about;1?what=sync-log {d28f8a0b-95da-48f4-b712-caf37097be41}
# Register resource aliases # Register resource aliases

View File

@ -107,3 +107,12 @@ maintenanceservice_installer::
$(NSINSTALL) -D $(DIST)/bin/ $(NSINSTALL) -D $(DIST)/bin/
cp $(CONFIG_DIR)/maintenanceservice_installer.exe $(DIST)/bin cp $(CONFIG_DIR)/maintenanceservice_installer.exe $(DIST)/bin
endif endif
ifdef MOZ_WEBAPP_RUNTIME
webapp_uninstaller::
$(INSTALL) $(addprefix $(MOZILLA_DIR)/toolkit/mozapps/installer/windows/nsis/,$(TOOLKIT_NSIS_FILES)) $(CONFIG_DIR)
$(INSTALL) $(addprefix $(MOZILLA_DIR)/other-licenses/nsis/Plugins/,$(CUSTOM_NSIS_PLUGINS)) $(CONFIG_DIR)
cd $(CONFIG_DIR) && $(MAKENSISU) webapp-uninstaller.nsi
$(NSINSTALL) -D $(DIST)/bin/
cp $(CONFIG_DIR)/webapp-uninstaller.exe $(DIST)/bin
endif

View File

@ -67,26 +67,65 @@ def lookup(path, l10ndirs):
return join(d, path) return join(d, path)
return join(l10ndirs[-1], path) return join(l10ndirs[-1], path)
def preprocess_locale_files(moz_dir, ab_cd, config_dir, l10ndirs): def preprocess_locale_files(config_dir, l10ndirs):
""" """
Preprocesses the installer localized properties files into the format Preprocesses the installer localized properties files into the format
required by NSIS and creates a basic NSIS nlf file. required by NSIS and creates a basic NSIS nlf file.
Parameters:
config_dir - the path to the destination directory
l10ndirs - list of paths to search for installer locale files
"""
# Create the main NSIS language file
fp = open_utf16le_file(join(config_dir, "overrideLocale.nsh"))
locale_strings = get_locale_strings(lookup("override.properties",
l10ndirs),
"LangString ^",
" 0 ",
False)
fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le"))
fp.close()
# Create the Modern User Interface language file
fp = open_utf16le_file(join(config_dir, "baseLocale.nsh"))
fp.write((u""";NSIS Modern User Interface - Language File
;Compatible with Modern UI 1.68
;Language: baseLocale (0)
!insertmacro MOZ_MUI_LANGUAGEFILE_BEGIN \"baseLocale\"
!define MUI_LANGNAME \"baseLocale\"
""").encode("utf-16-le"))
locale_strings = get_locale_strings(lookup("mui.properties", l10ndirs),
"!define ", " ", True)
fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le"))
fp.write(u"!insertmacro MOZ_MUI_LANGUAGEFILE_END\n".encode("utf-16-le"))
fp.close()
# Create the custom language file for our custom strings
fp = open_utf16le_file(join(config_dir, "customLocale.nsh"))
locale_strings = get_locale_strings(lookup("custom.properties",
l10ndirs),
"LangString ",
" 0 ",
True)
fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le"))
fp.close()
def create_nlf_file(moz_dir, ab_cd, config_dir):
"""
Create a basic NSIS nlf file.
Parameters: Parameters:
moz_dir - the path to top source directory for the toolkit source moz_dir - the path to top source directory for the toolkit source
ab_cd - the locale code ab_cd - the locale code
config_dir - the path to the destination directory config_dir - the path to the destination directory
l10ndirs - list of paths to search for installer locale files
""" """
# Set the language ID to 0 to make this locale the default locale. An
# actual ID will need to be used to create a multi-language installer
# (e.g. for CD distributions, etc.).
lang_id = "0"
rtl = "-" rtl = "-"
# Check whether the locale is right to left from locales.nsi. # Check whether the locale is right to left from locales.nsi.
fp = open(join(moz_dir, "toolkit/mozapps/installer/windows/nsis/locales.nsi"), "r") fp = open(join(moz_dir,
"toolkit/mozapps/installer/windows/nsis/locales.nsi"),
"r")
for line in fp: for line in fp:
line = line.strip() line = line.strip()
if line == "!define " + ab_cd + "_rtl": if line == "!define " + ab_cd + "_rtl":
@ -103,7 +142,7 @@ def preprocess_locale_files(moz_dir, ab_cd, config_dir, l10ndirs):
NLF v6 NLF v6
# Start editing here # Start editing here
# Language ID # Language ID
%s 0
# Font and size - dash (-) means default # Font and size - dash (-) means default
- -
- -
@ -111,37 +150,35 @@ NLF v6
- -
# RTL - anything else than RTL means LTR # RTL - anything else than RTL means LTR
%s %s
""" % (lang_id, rtl)).encode("utf-16-le")) """ % rtl).encode("utf-16-le"))
fp.close() fp.close()
# Create the main NSIS language file def preprocess_locale_file(config_dir,
fp = open_utf16le_file(join(config_dir, "overrideLocale.nsh")) l10ndirs,
locale_strings = get_locale_strings(lookup("override.properties", l10ndirs), properties_filename,
"LangString ^", " " + lang_id + " ", False) output_filename):
fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) """
fp.close() Preprocesses a single localized properties file into the format
required by NSIS and creates a basic NSIS nlf file.
# Create the Modern User Interface language file Parameters:
fp = open_utf16le_file(join(config_dir, "baseLocale.nsh")) config_dir - the path to the destination directory
fp.write((u""";NSIS Modern User Interface - Language File l10ndirs - list of paths to search for installer locale files
;Compatible with Modern UI 1.68 properties_filename - the name of the properties file to search for
;Language: baseLocale (%s) output_filename - the output filename to write
!insertmacro MOZ_MUI_LANGUAGEFILE_BEGIN \"baseLocale\" """
!define MUI_LANGNAME \"baseLocale\"
""" % (lang_id)).encode("utf-16-le"))
locale_strings = get_locale_strings(lookup("mui.properties", l10ndirs),
"!define ", " ", True)
fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le"))
fp.write(u"!insertmacro MOZ_MUI_LANGUAGEFILE_END\n".encode("utf-16-le"))
fp.close()
# Create the custom language file for our custom strings # Create the custom language file for our custom strings
fp = open_utf16le_file(join(config_dir, "customLocale.nsh")) fp = open_utf16le_file(join(config_dir, output_filename))
locale_strings = get_locale_strings(lookup("custom.properties", l10ndirs), locale_strings = get_locale_strings(lookup(properties_filename,
"LangString ", " " + lang_id + " ", True) l10ndirs),
"LangString ",
" 0 ",
True)
fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le"))
fp.close() fp.close()
def convert_utf8_utf16le(in_file_path, out_file_path): def convert_utf8_utf16le(in_file_path, out_file_path):
""" """
Converts a UTF-8 file to a new UTF-16LE file Converts a UTF-8 file to a new UTF-16LE file
@ -160,11 +197,13 @@ if __name__ == '__main__':
usage = """usage: %prog command <args> usage = """usage: %prog command <args>
Commands: Commands:
--convert-utf8-utf16le - preprocesses installer locale properties files and --convert-utf8-utf16le - Preprocesses installer locale properties files
creates a basic NSIS nlf file --preprocess-locale - Preprocesses the installer localized properties
--preprocess-locale - Preprocesses the installer localized properties files files into the format required by NSIS and
into the format required by NSIS and creates a basic creates a basic NSIS nlf file.
NSIS nlf file. --preprocess-single-file - Preprocesses a single properties file into the
format required by NSIS
--create-nlf-file - Creates a basic NSIS nlf file
preprocess-locale.py --preprocess-locale <src> <locale> <code> <dest> preprocess-locale.py --preprocess-locale <src> <locale> <code> <dest>
@ -175,15 +214,61 @@ Arguments:
<dest> \tthe path to the destination directory <dest> \tthe path to the destination directory
preprocess-locale.py --preprocess-single-file <src>
<locale>
<dest>
<infile>
<outfile>
Arguments:
<src> \tthe path to top source directory for the toolkit source
<locale> \tthe path to the installer's locale files
<dest> \tthe path to the destination directory
<infile> \tthe properties file to process
<outfile>\tthe nsh file to write
preprocess-locale.py --create-nlf-file <src>
<code>
<dest>
Arguments:
<src> \tthe path to top source directory for the toolkit source
<code> \tthe locale code
<dest> \tthe path to the destination directory
preprocess-locale.py --convert-utf8-utf16le <src> <dest> preprocess-locale.py --convert-utf8-utf16le <src> <dest>
Arguments: Arguments:
<src> \tthe path to the UTF-8 source file to convert <src> \tthe path to the UTF-8 source file to convert
<dest>\tthe path to the UTF-16LE destination file to create <dest>\tthe path to the UTF-16LE destination file to create
""" """
preprocess_locale_args_help_string = """\
Arguments to --preprocess-locale should be:
<src> <locale> <code> <dest>
or
<src> <code> <dest> --l10n-dir <dir> [--l10n-dir <dir> ...]"""
preprocess_single_file_args_help_string = """\
Arguments to --preprocess-single_file should be:
<src> <locale> <code> <dest> <infile> <outfile>
or
<src> <locale> <code> <dest> <infile> <outfile>
--l10n-dir <dir> [--l10n-dir <dir>...]"""
create_nlf_args_help_string = """\
Arguments to --create-nlf-file should be:
<src> <code> <dest>"""
p = OptionParser(usage=usage) p = OptionParser(usage=usage)
p.add_option("--preprocess-locale", action="store_true", default=False, p.add_option("--preprocess-locale", action="store_true", default=False,
dest='preprocess') dest='preprocess')
p.add_option("--preprocess-single-file", action="store_true", default=False,
dest='preprocessSingle')
p.add_option("--create-nlf-file", action="store_true", default=False,
dest='createNlf')
p.add_option("--l10n-dir", action="append", default=[], p.add_option("--l10n-dir", action="append", default=[],
dest="l10n_dirs", dest="l10n_dirs",
help="Add directory to lookup for locale files") help="Add directory to lookup for locale files")
@ -192,25 +277,84 @@ Arguments:
options, args = p.parse_args() options, args = p.parse_args()
if ((not (options.preprocess or options.convert)) or foundOne = False
(options.preprocess and options.convert)): if (options.preprocess):
p.error("You need to specify either --preprocess-locale or --convert-utf-utf16le") foundOne = True
if (options.convert):
if(foundOne):
p.error("More than one command specified")
else:
foundOne = True
if (options.preprocessSingle):
if(foundOne):
p.error("More than one command specified")
else:
foundOne = True
if (options.createNlf):
if(foundOne):
p.error("More than one command specified")
else:
foundOne = True
if (not foundOne):
p.error("No command specified")
if options.preprocess: if options.preprocess:
if len(args) not in (3,4): if len(args) not in (3,4):
p.error("--preprocess-locale needs all of <src> <locale> <code> <dest>") p.error(preprocess_locale_args_help_string)
# Parse args
pargs = args[:] pargs = args[:]
if len(args) == 4: moz_dir = pargs[0]
l10n_dirs = [args[1]] if len(pargs) == 4:
l10n_dirs = [pargs[1]]
del pargs[1] del pargs[1]
else: else:
if not options.l10n_dirs: if not options.l10n_dirs:
p.error("--preprocess-locale needs either <locale> or --l10ndir") p.error(preprocess_locale_args_help_string)
l10n_dirs = options.l10n_dirs l10n_dirs = options.l10n_dirs
ab_cd = pargs[1]
config_dir = pargs[2]
pargs.append(l10n_dirs) # Create the output files
preprocess_locale_files(*pargs) create_nlf_file(moz_dir, ab_cd, config_dir)
else: preprocess_locale_files(config_dir, l10n_dirs)
elif options.preprocessSingle:
if len(args) not in (4,5):
p.error(preprocess_single_file_args_help_string)
# Parse args
pargs = args[:]
moz_dir = pargs[0]
if len(pargs) == 5:
l10n_dirs = [pargs[1]]
del pargs[1]
else:
if not options.l10n_dirs:
p.error(preprocess_single_file_args_help_string)
l10n_dirs = options.l10n_dirs
config_dir = pargs[1]
in_file = pargs[2]
out_file = pargs[3]
# Create the output files
preprocess_locale_file(config_dir,
l10n_dirs,
in_file,
out_file)
elif options.createNlf:
if len(args) != 3:
p.error(create_nlf_args_help_string)
# Parse args
pargs = args[:]
moz_dir = pargs[0]
ab_cd = pargs[1]
config_dir = pargs[2]
# Create the output files
create_nlf_file(moz_dir, ab_cd, config_dir)
elif options.convert:
if len(args) != 2: if len(args) != 2:
p.error("--convert-utf8-utf16le needs both of <src> <dest>") p.error("--convert-utf8-utf16le needs both of <src> <dest>")
convert_utf8_utf16le(*args) convert_utf8_utf16le(*args)

View File

@ -99,6 +99,8 @@
#define PREF_OVERRIDE_DIRNAME "preferences" #define PREF_OVERRIDE_DIRNAME "preferences"
#define WEBAPPRT_APPID "webapprt@mozilla.org"
static already_AddRefed<nsILocalFile> static already_AddRefed<nsILocalFile>
CloneAndAppend(nsIFile* aFile, const char* name) CloneAndAppend(nsIFile* aFile, const char* name)
{ {
@ -425,24 +427,26 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
} }
static void static void
LoadAppDirIntoArray(nsIFile* aXULAppDir, LoadDirIntoArray(nsIFile* dir,
const char *const *aAppendList, const char *const *aAppendList,
nsCOMArray<nsIFile>& aDirectories) nsCOMArray<nsIFile>& aDirectories)
{ {
if (!aXULAppDir) if (!dir)
return; return;
nsCOMPtr<nsIFile> subdir; nsCOMPtr<nsIFile> subdir;
aXULAppDir->Clone(getter_AddRefs(subdir)); dir->Clone(getter_AddRefs(subdir));
if (!subdir) if (!subdir)
return; return;
for (; *aAppendList; ++aAppendList) for (const char *const *a = aAppendList; *a; ++a) {
subdir->AppendNative(nsDependentCString(*aAppendList)); subdir->AppendNative(nsDependentCString(*a));
}
bool exists; bool exists;
if (NS_SUCCEEDED(subdir->Exists(&exists)) && exists) if (NS_SUCCEEDED(subdir->Exists(&exists)) && exists) {
aDirectories.AppendObject(subdir); aDirectories.AppendObject(subdir);
}
} }
static void static void
@ -461,12 +465,10 @@ LoadDirsIntoArray(nsCOMArray<nsIFile>& aSourceDirs,
nsCAutoString leaf; nsCAutoString leaf;
appended->GetNativeLeafName(leaf); appended->GetNativeLeafName(leaf);
if (!Substring(leaf, leaf.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi"))) { if (!Substring(leaf, leaf.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi"))) {
for (const char *const *a = aAppendList; *a; ++a) LoadDirIntoArray(appended,
appended->AppendNative(nsDependentCString(*a)); aAppendList,
aDirectories);
} }
if (NS_SUCCEEDED(appended->Exists(&exists)) && exists)
aDirectories.AppendObject(appended);
} }
} }
@ -642,10 +644,17 @@ nsXREDirProvider::GetFilesInternal(const char* aProperty,
else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) { else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
nsCOMArray<nsIFile> directories; nsCOMArray<nsIFile> directories;
LoadAppDirIntoArray(mXULAppDir, kAppendPrefDir, directories); LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories);
LoadDirsIntoArray(mAppBundleDirectories, LoadDirsIntoArray(mAppBundleDirectories,
kAppendPrefDir, directories); kAppendPrefDir, directories);
// Include the WebappRT-specific prefs dir if we're running WebappRT.
if (gAppData && !strcmp(gAppData->ID, WEBAPPRT_APPID)) {
const char *const kAppendAppIDPrefDir[] =
{ "defaults", "pref", gAppData->ID, nsnull };
LoadDirIntoArray(mXULAppDir, kAppendAppIDPrefDir, directories);
}
rv = NS_NewArrayEnumerator(aResult, directories); rv = NS_NewArrayEnumerator(aResult, directories);
} }
else if (!strcmp(aProperty, NS_EXT_PREFS_DEFAULTS_DIR_LIST)) { else if (!strcmp(aProperty, NS_EXT_PREFS_DEFAULTS_DIR_LIST)) {
@ -672,9 +681,9 @@ nsXREDirProvider::GetFilesInternal(const char* aProperty,
static const char *const kAppendChromeDir[] = { "chrome", nsnull }; static const char *const kAppendChromeDir[] = { "chrome", nsnull };
nsCOMArray<nsIFile> directories; nsCOMArray<nsIFile> directories;
LoadAppDirIntoArray(mXULAppDir, LoadDirIntoArray(mXULAppDir,
kAppendChromeDir, kAppendChromeDir,
directories); directories);
LoadDirsIntoArray(mAppBundleDirectories, LoadDirsIntoArray(mAppBundleDirectories,
kAppendChromeDir, kAppendChromeDir,
directories); directories);

48
webapprt/Makefile.in Normal file
View File

@ -0,0 +1,48 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
DEPTH = ..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(topsrcdir)/config/config.mk
DIRS = $(NULL)
ifneq (,$(filter WINNT,$(OS_ARCH)))
DIRS += win
else
ifeq ($(OS_ARCH),Darwin)
DIRS += mac
endif # mac
endif # windows
EXTRA_PP_COMPONENTS = \
WebappRTComponents.manifest \
WebappRTCommandLineHandler.js \
WebappRTDirectoryProvider.js \
$(NULL)
EXTRA_JS_MODULES = \
WebappRT.jsm \
$(NULL)
include $(topsrcdir)/config/rules.mk
libs:: prefs.js
$(NSINSTALL) -D $(DIST)/bin/defaults/pref/webapprt@mozilla.org
$(INSTALL) $^ $(DIST)/bin/defaults/pref/webapprt@mozilla.org
GRE_MILESTONE := $(shell tail -n 1 $(topsrcdir)/config/milestone.txt 2>/dev/null || tail -1 $(topsrcdir)/config/milestone.txt)
GRE_BUILDID := $(shell cat $(DEPTH)/config/buildid)
DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DGRE_BUILDID=$(GRE_BUILDID)
webapprt.ini: webapprt.ini.in $(DEPTH)/config/buildid $(topsrcdir)/config/milestone.txt
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $< > $@
libs:: webapprt.ini
$(INSTALL) webapprt.ini $(DIST)/bin
GARBAGE += webapprt.ini

55
webapprt/WebappRT.jsm Normal file
View File

@ -0,0 +1,55 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const EXPORTED_SYMBOLS = ["WebappRT"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "FileUtils", function() {
Cu.import("resource://gre/modules/FileUtils.jsm");
return FileUtils;
});
let WebappRT = {
get config() {
let webappFile = FileUtils.getFile("AppRegD", ["webapp.json"]);
let inputStream = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
inputStream.init(webappFile, -1, 0, 0);
let json = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
let config = json.decodeFromStream(inputStream, webappFile.fileSize);
// Memoize the getter, freezing the `config` object in the meantime so
// consumers don't inadvertently (or intentionally) change it, as the object
// is meant to be a read-only representation of the webapp's configuration.
config = deepFreeze(config);
delete this.config;
Object.defineProperty(this, "config", { get: function getConfig() config });
return this.config;
}
};
function deepFreeze(o) {
// First, freeze the object.
Object.freeze(o);
// Then recursively call deepFreeze() to freeze its properties.
for (let p in o) {
// If the object is on the prototype, not an object, or is already frozen,
// skip it. Note that this might leave an unfrozen reference somewhere in
// the object if there is an already frozen object containing an unfrozen
// object.
if (!o.hasOwnProperty(p) || !(typeof o[p] == "object") ||
Object.isFrozen(o[p]))
continue;
deepFreeze(o[p]);
}
return o;
}

View File

@ -0,0 +1,31 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
function CommandLineHandler() {}
CommandLineHandler.prototype = {
classID: Components.ID("{6d69c782-40a3-469b-8bfd-3ee366105a4a}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]),
handle: function handle(cmdLine) {
Services.ww.openWindow(null,
"chrome://webapprt/content/webapp.xul",
"_blank",
"chrome,dialog=no,all,resizable",
null);
},
helpInfo : "",
};
let components = [CommandLineHandler];
let NSGetFactory = XPCOMUtils.generateNSGetFactory(components);

View File

@ -0,0 +1,9 @@
# WebappRTCommandLineHandler.js
component {6d69c782-40a3-469b-8bfd-3ee366105a4a} WebappRTCommandLineHandler.js application=webapprt@mozilla.org
contract @mozilla.org/webapprt/clh;1 {6d69c782-40a3-469b-8bfd-3ee366105a4a} application=webapprt@mozilla.org
category command-line-handler x-default @mozilla.org/webapprt/clh;1 application=webapprt@mozilla.org
# WebappRTDirectoryProvider.js
component {e1799fda-4b2f-4457-b671-e0641d95698d} WebappRTDirectoryProvider.js application=webapprt@mozilla.org
contract @mozilla.org/webapprt/directory-provider;1 {e1799fda-4b2f-4457-b671-e0641d95698d} application=webapprt@mozilla.org
category xpcom-directory-providers webapprt-directory-provider @mozilla.org/webapprt/directory-provider;1 application=webapprt@mozilla.org

View File

@ -0,0 +1,34 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const WEBAPP_REGISTRY_DIR = "WebappRegD";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/WebappRT.jsm");
function DirectoryProvider() {}
DirectoryProvider.prototype = {
classID: Components.ID("{e1799fda-4b2f-4457-b671-e0641d95698d}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider]),
getFile: function(prop, persistent) {
if (prop == WEBAPP_REGISTRY_DIR) {
let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
dir.initWithPath(WebappRT.config.registryDir);
return dir;
}
// We return null to show failure instead of throwing an error,
// which works with the way the interface is called (per bug 529077).
return null;
}
};
const NSGetFactory = XPCOMUtils.generateNSGetFactory([DirectoryProvider]);

View File

@ -0,0 +1,77 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/WebappRT.jsm");
Cu.import("resource://gre/modules/Services.jsm");
function onLoad() {
window.removeEventListener("load", onLoad, false);
let installRecord = WebappRT.config.app;
let manifest = WebappRT.config.app.manifest;
// Set the title of the window to the name of the webapp.
document.documentElement.setAttribute("title", manifest.name);
// Load the webapp's launch path.
let url = Services.io.newURI(installRecord.origin, null, null);
if (manifest.launch_path)
url = Services.io.newURI(manifest.launch_path, null, url);
document.getElementById("content").setAttribute("src", url.spec);
}
window.addEventListener("load", onLoad, false);
#ifdef XP_MACOSX
// On Mac, we dynamically create the label for the Quit menuitem, using
// a string property to inject the name of the webapp into it.
window.addEventListener("load", function onLoadUpdateMenuItems() {
window.removeEventListener("load", onLoadUpdateMenuItems, false);
let installRecord = WebappRT.config.app;
let manifest = WebappRT.config.app.manifest;
let bundle =
Services.strings.createBundle("chrome://webapprt/locale/webapp.properties");
let quitLabel = bundle.formatStringFromName("quitApplicationCmdMac.label",
[manifest.name], 1);
let hideLabel = bundle.formatStringFromName("hideApplicationCmdMac.label",
[manifest.name], 1);
document.getElementById("menu_FileQuitItem").setAttribute("label", quitLabel);
document.getElementById("menu_mac_hide_app").setAttribute("label", hideLabel);
}, false);
#endif
function updateEditUIVisibility() {
#ifndef XP_MACOSX
let editMenuPopupState = document.getElementById("menu_EditPopup").state;
// The UI is visible if the Edit menu is opening or open, if the context menu
// is open, or if the toolbar has been customized to include the Cut, Copy,
// or Paste toolbar buttons.
gEditUIVisible = editMenuPopupState == "showing" ||
editMenuPopupState == "open";
// If UI is visible, update the edit commands' enabled state to reflect
// whether or not they are actually enabled for the current focus/selection.
if (gEditUIVisible) {
goUpdateGlobalEditMenuItems();
}
// Otherwise, enable all commands, so that keyboard shortcuts still work,
// then lazily determine their actual enabled state when the user presses
// a keyboard shortcut.
else {
goSetCommandEnabled("cmd_undo", true);
goSetCommandEnabled("cmd_redo", true);
goSetCommandEnabled("cmd_cut", true);
goSetCommandEnabled("cmd_copy", true);
goSetCommandEnabled("cmd_paste", true);
goSetCommandEnabled("cmd_selectAll", true);
goSetCommandEnabled("cmd_delete", true);
goSetCommandEnabled("cmd_switchTextDirection", true);
}
#endif
}

156
webapprt/content/webapp.xul Normal file
View File

@ -0,0 +1,156 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
<!DOCTYPE window [
<!ENTITY % webappDTD SYSTEM "chrome://webapprt/locale/webapp.dtd">
%webappDTD;
]>
<window windowtype="webapprt:webapp"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
width="1024" height="768">
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="application/javascript" src="chrome://webapprt/content/webapp.js"/>
<commandset id="mainCommandSet">
<command id="cmd_quitApplication" oncommand="goQuitApplication()"/>
<commandset id="editMenuCommands"/>
</commandset>
<keyset id="mainKeyset">
<key id="key_undo"
key="&undoCmd.key;"
modifiers="accel"/>
<key id="key_redo" key="&undoCmd.key;" modifiers="accel,shift"/>
<key id="key_cut"
key="&cutCmd.key;"
modifiers="accel"/>
<key id="key_copy"
key="&copyCmd.key;"
modifiers="accel"/>
<key id="key_paste"
key="&pasteCmd.key;"
modifiers="accel"/>
<key id="key_delete" keycode="VK_DELETE" command="cmd_delete"/>
<key id="key_selectAll" key="&selectAllCmd.key;" modifiers="accel"/>
<key id="key_quitApplication"
key="&quitApplicationCmdMac.key;"
command="cmd_quitApplication"
modifiers="accel"/>
<key id="key_hideThisAppCmdMac"
key="&hideThisAppCmdMac.key;"
modifiers="accel"/>
<key id="key_hideOtherAppsCmdMac"
key="&hideOtherAppsCmdMac.key;"
modifiers="accel,alt"/>
</keyset>
<menubar id="main-menubar">
#ifndef XP_MACOSX
<!-- On Mac, the Quit item gets moved to the Application menu by nsMenuBarX.
- And right now it's the only item in the File menu. So if we put it
- into that menu on Mac, the File menu shows up empty on that OS.
- To work around that problem, we put the item into the Edit menu on Mac
- (from which nsMenuBarX still moves it properly), and we don't create
- the File menu in the first place on that OS.
-
- But if you are adding a persistent item to the File menu on Mac,
- then that workaround is no longer necessary, and you can move the Quit
- item up here. -->
<menu id="file-menu" label="&fileMenu.label;"
accesskey="&fileMenu.accesskey;">
<menupopup id="menu_FilePopup">
<menuitem id="menu_FileQuitItem"
#ifdef XP_WIN
label="&quitApplicationCmdWin.label;"
accesskey="&quitApplicationCmdWin.accesskey;"
#else
label="&quitApplicationCmd.label;"
accesskey="&quitApplicationCmd.accesskey;"
#endif
#ifdef XP_UNIX
key="key_quitApplication"
#endif
command="cmd_quitApplication"/>
</menupopup>
</menu>
#endif
<menu id="edit-menu" label="&editMenu.label;"
accesskey="&editMenu.accesskey;">
<menupopup id="menu_EditPopup"
onpopupshowing="updateEditUIVisibility()"
onpopuphidden="updateEditUIVisibility()">
#ifdef XP_MACOSX
<!-- These items get moved to the Application menu by nsMenuBarX.
- They can live in any menu.
-
- See the comment on the File menu above for why the Quit item is
- here, and note that JavaScript code dynamically updates the labels
- of the Quit and Hide items, which include the name of the app. -->
<menuitem id="menu_FileQuitItem"
label="&quitApplicationCmd.label;"
key="key_quitApplication"
command="cmd_quitApplication"/>
<menuitem id="menu_mac_hide_app"
key="key_hideThisAppCmdMac"/>
<menuitem id="menu_mac_hide_others"
label="&hideOtherAppsCmdMac.label;"
key="key_hideOtherAppsCmdMac"/>
<menuitem id="menu_mac_show_all" label="&showAllAppsCmdMac.label;"/>
#endif
<menuitem id="menu_undo"
label="&undoCmd.label;"
key="key_undo"
accesskey="&undoCmd.accesskey;"
command="cmd_undo"/>
<menuitem id="menu_redo"
label="&redoCmd.label;"
key="key_redo"
accesskey="&redoCmd.accesskey;"
command="cmd_redo"/>
<menuseparator/>
<menuitem id="menu_cut"
label="&cutCmd.label;"
key="key_cut"
accesskey="&cutCmd.accesskey;"
command="cmd_cut"/>
<menuitem id="menu_copy"
label="&copyCmd.label;"
key="key_copy"
accesskey="&copyCmd.accesskey;"
command="cmd_copy"/>
<menuitem id="menu_paste"
label="&pasteCmd.label;"
key="key_paste"
accesskey="&pasteCmd.accesskey;"
command="cmd_paste"/>
<menuitem id="menu_delete"
label="&deleteCmd.label;"
key="key_delete"
accesskey="&deleteCmd.accesskey;"
command="cmd_delete"/>
<menuseparator/>
<menuitem id="menu_selectAll"
label="&selectAllCmd.label;"
key="key_selectAll"
accesskey="&selectAllCmd.accesskey;"
command="cmd_selectAll"/>
</menupopup>
</menu>
</menubar>
<browser type="content" id="content" flex="1"/>
</window>

4
webapprt/jar.mn Normal file
View File

@ -0,0 +1,4 @@
webapprt.jar:
% content webapprt %content/
* content/webapp.js (content/webapp.js)
* content/webapp.xul (content/webapp.xul)

View File

@ -0,0 +1,10 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
# LOCALIZATION NOTE: This file must be saved as UTF8
# LOCALIZATION NOTE: $AppName will be replaced with the (already localized)
# name of the webapp being uninstalled.
^UninstallCaption=$AppName Uninstall
UN_CONFIRM_UNINSTALL=$AppName will be uninstalled from your computer.

47
webapprt/mac/Makefile.in Normal file
View File

@ -0,0 +1,47 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
# This switches $(INSTALL) to copy mode, like $(SYSINSTALL), so things that
# shouldn't get 755 perms need $(IFLAGS1) for either way of calling nsinstall.
NSDISTMODE = copy
include $(topsrcdir)/config/config.mk
PROGRAM = webapprt-stub$(BIN_SUFFIX)
CMMSRCS = webapprt.mm
# Don't create a dependency on mozglue, which is impossible (difficult?)
# to dynamically link into our executable, as we copy it to arbitrary locations.
MOZ_GLUE_LDFLAGS =
MOZ_GLUE_PROGRAM_LDFLAGS =
# mozglue uses mfbt's Assertions.cpp, which provides MOZ_ASSERT, which lots
# of code in libxpcom uses, so we have to do the same.
VPATH += $(topsrcdir)/mfbt
CPPSRCS = Assertions.cpp
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
LOCAL_INCLUDES += -I$(DEPTH)/build
DEFINES += -DXPCOM_GLUE
STL_FLAGS=
LIBS = \
$(XPCOM_STANDALONE_GLUE_LDOPTS) \
$(NULL)
include $(topsrcdir)/config/rules.mk
GRE_BUILDID := $(shell cat $(DEPTH)/config/buildid)
DEFINES += -DGRE_BUILDID=$(GRE_BUILDID)
webapprt.$(OBJ_SUFFIX): $(DEPTH)/config/buildid

356
webapprt/mac/webapprt.mm Normal file
View File

@ -0,0 +1,356 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
//PLAN:
// open my bundle, check for an override binary signature
// find the newest firefox. open its bundle, get the version number.
// if the firefox version is different than ours:
// delete our own binary,
// copy the newer webapprt binary from Firefox
// exec it, and quit
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <Cocoa/Cocoa.h>
#include <Foundation/Foundation.h>
#include "nsXPCOMGlue.h"
#include "nsINIParser.h"
#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
#include "nsXULAppAPI.h"
#include "nsComponentManagerUtils.h"
#include "nsCOMPtr.h"
#include "nsILocalFile.h"
#include "nsStringGlue.h"
const char WEBAPPRT_EXECUTABLE[] = "webapprt-stub";
const char FXAPPINI_NAME[] = "application.ini";
const char WEBAPPINI_NAME[] = "webapp.ini";
const char WEBRTINI_NAME[] = "webapprt.ini";
//need the correct relative path here
const char APP_CONTENTS_PATH[] = "/Contents/MacOS/";
void ExecNewBinary(NSString* launchPath);
NSString *PathToWebRT(NSString* alternateBinaryID);
NSException* MakeException(NSString* name, NSString* message);
void DisplayErrorAlert(NSString* title, NSString* message);
XRE_GetFileFromPathType XRE_GetFileFromPath;
XRE_CreateAppDataType XRE_CreateAppData;
XRE_FreeAppDataType XRE_FreeAppData;
XRE_mainType XRE_main;
const nsDynamicFunctionLoad kXULFuncs[] = {
{ "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
{ "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
{ "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
{ "XRE_main", (NSFuncPtr*) &XRE_main },
{ nsnull, nsnull }
};
nsresult
AttemptGRELoad(char *greDir)
{
nsresult rv;
char xpcomDLLPath[MAXPATHLEN];
snprintf(xpcomDLLPath, MAXPATHLEN, "%s%s", greDir, XPCOM_DLL);
rv = XPCOMGlueStartup(xpcomDLLPath);
if (NS_FAILED(rv)) {
return rv;
}
rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
if (NS_FAILED(rv)) {
return rv;
}
return rv;
}
// Copied from toolkit/xre/nsAppData.cpp.
void
SetAllocatedString(const char *&str, const char *newvalue)
{
NS_Free(const_cast<char*>(str));
if (newvalue) {
str = NS_strdup(newvalue);
} else {
str = nsnull;
}
}
int
main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *firefoxPath = nil;
NSString *alternateBinaryID = nil;
//this is our version, to be compared with the version of the binary we are asked to use
NSString* myVersion = [NSString stringWithFormat:@"%s", NS_STRINGIFY(GRE_BUILDID)];
NSLog(@"MY WEBAPPRT BUILDID: %@", myVersion);
//I need to look in our bundle first, before deciding what firefox binary to use
NSBundle* myBundle = [NSBundle mainBundle];
NSString* myBundlePath = [myBundle bundlePath];
alternateBinaryID = [myBundle objectForInfoDictionaryKey:@"FirefoxBinary"];
NSLog(@"found override firefox binary: %@", alternateBinaryID);
@try {
//find a webapprt binary to launch with. throws an exception with error dialog if none found.
firefoxPath = PathToWebRT(alternateBinaryID);
NSLog(@"USING FIREFOX : %@", firefoxPath);
NSString *myWebRTPath = [myBundle pathForAuxiliaryExecutable: @"webapprt"];
if (!myWebRTPath) {
@throw MakeException(@"Missing WebRT Files", @"Cannot locate binary for this application");
}
//GET FIREFOX BUILD ID
NSString *firefoxINIFilePath = [NSString stringWithFormat:@"%@%s%s", firefoxPath, APP_CONTENTS_PATH, FXAPPINI_NAME];
nsINIParser ffparser;
NSLog(@"Looking for firefox ini file here: %@", firefoxINIFilePath);
if (NS_FAILED(ffparser.Init([firefoxINIFilePath UTF8String]))) {
NSLog(@"Unable to locate Firefox application.ini");
@throw MakeException(@"Error", @"Unable to parse environment files for application startup");
}
char ffVersChars[MAXPATHLEN];
if (NS_FAILED(ffparser.GetString("App", "BuildID", ffVersChars, MAXPATHLEN))) {
NSLog(@"Unable to retrieve Firefox BuildID");
@throw MakeException(@"Error", @"Unable to determine Firefox version.");
}
NSString* firefoxVersion = [NSString stringWithFormat:@"%s", ffVersChars];
NSLog(@"FIREFOX WEBAPPRT BUILDID: %@", firefoxVersion);
//GOT FIREFOX BUILD ID
//COMPARE MY BUILD ID AND FIREFOX BUILD ID
if ([myVersion compare: firefoxVersion] != NSOrderedSame) {
//we are going to assume that if they are different, we need to re-copy the webapprt, regardless of whether
// it is newer or older. If we don't find a webapprt, then the current Firefox must not be new enough to run webapps.
NSLog(@"### This Application has an old webrt. Updating it.");
NSLog(@"### My webapprt path: %@", myWebRTPath);
NSFileManager* fileClerk = [[NSFileManager alloc] init];
NSError *errorDesc = nil;
//we know the firefox path, so copy the new webapprt here
NSString *newWebRTPath = [NSString stringWithFormat: @"%@%s%s", firefoxPath, APP_CONTENTS_PATH, WEBAPPRT_EXECUTABLE];
NSLog(@"### Firefox webapprt path: %@", newWebRTPath);
if (![fileClerk fileExistsAtPath:newWebRTPath]) {
NSString* msg = [NSString stringWithFormat: @"This version of Firefox (%@) cannot run web applications, because it is not recent enough or damaged", firefoxVersion];
@throw MakeException(@"Missing WebRT Files", msg);
}
[fileClerk removeItemAtPath: myWebRTPath error: &errorDesc];
if (errorDesc != nil) {
NSLog(@"failed to unlink old binary file at path: %@ with error: %@", myWebRTPath, errorDesc);
@throw MakeException(@"Unable To Update", @"Failed preparation for runtime update");
}
[fileClerk copyItemAtPath: newWebRTPath toPath: myWebRTPath error: &errorDesc];
[fileClerk release];
if (errorDesc != nil) {
NSLog(@"failed to copy new webrt file: %@", errorDesc);
@throw MakeException(@"Unable To Update", @"Failed to update runtime");
} else {
NSLog(@"### Successfully updated webapprt, relaunching");
}
//execv the new binary, and ride off into the sunset
ExecNewBinary(myWebRTPath);
} else {
//we are ready to load XUL and such, and go go go
NSLog(@"This Application has the newest webrt. Launching!");
int result = 0;
char rtINIPath[MAXPATHLEN];
// Set up our environment to know where webapp.ini was loaded from.
char appEnv[MAXPATHLEN];
snprintf(appEnv, MAXPATHLEN, "%s%s%s", [myBundlePath UTF8String], APP_CONTENTS_PATH, WEBAPPINI_NAME);
if (setenv("XUL_APP_FILE", appEnv, 1)) {
NSLog(@"Couldn't set XUL_APP_FILE to: %s", appEnv);
@throw MakeException(@"Error", @"Unable to set webapp INI file.");
}
NSLog(@"Set XUL_APP_FILE to: %s", appEnv);
//CONSTRUCT GREDIR AND CALL XPCOMGLUE WITH IT
char greDir[MAXPATHLEN];
snprintf(greDir, MAXPATHLEN, "%s%s", [firefoxPath UTF8String], APP_CONTENTS_PATH);
if (!NS_SUCCEEDED(AttemptGRELoad(greDir))) {
@throw MakeException(@"Error", @"Unable to load XUL files for application startup");
}
// NOTE: The GRE has successfully loaded, so we can use XPCOM now
NS_LogInit();
{ // Scope for any XPCOM stuff we create
nsINIParser parser;
if (NS_FAILED(parser.Init(appEnv))) {
NSLog(@"%s was not found\n", appEnv);
@throw MakeException(@"Error", @"Unable to parse environment files for application startup");
}
// Get the path to the runtime's INI file. This should be in the
// same directory as the GRE.
snprintf(rtINIPath, MAXPATHLEN, "%s%s%s", [firefoxPath UTF8String], APP_CONTENTS_PATH, WEBRTINI_NAME);
NSLog(@"webapprt.ini path: %s", rtINIPath);
if (![[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%s", rtINIPath]]) {
NSString* msg = [NSString stringWithFormat: @"This copy of Firefox (%@) cannot run web applications, because it is missing important files", firefoxVersion];
@throw MakeException(@"Missing WebRT Files", msg);
}
// Load the runtime's INI from its path.
nsCOMPtr<nsILocalFile> rtINI;
if (NS_FAILED(XRE_GetFileFromPath(rtINIPath, getter_AddRefs(rtINI)))) {
NSLog(@"Runtime INI path not recognized: '%s'\n", rtINIPath);
@throw MakeException(@"Error", @"Incorrect path to base INI file.");
}
if (!rtINI) {
NSLog(@"Error: missing webapprt.ini");
@throw MakeException(@"Error", @"Missing base INI file.");
}
nsXREAppData *webShellAppData;
if (NS_FAILED(XRE_CreateAppData(rtINI, &webShellAppData))) {
NSLog(@"Couldn't read webapprt.ini: %s", rtINIPath);
@throw MakeException(@"Error", @"Unable to parse base INI file.");
}
char profile[MAXPATHLEN];
if (NS_FAILED(parser.GetString("Webapp", "Profile", profile, MAXPATHLEN))) {
NSLog(@"Unable to retrieve profile from web app INI file");
@throw MakeException(@"Error", @"Unable to retrieve installation profile.");
}
NSLog(@"setting app profile: %s", profile);
SetAllocatedString(webShellAppData->profile, profile);
nsCOMPtr<nsILocalFile> directory;
if (NS_FAILED(XRE_GetFileFromPath(greDir, getter_AddRefs(directory)))) {
NSLog(@"Unable to open app dir");
@throw MakeException(@"Error", @"Unable to open application directory.");
}
nsCOMPtr<nsILocalFile> xreDir;
if (NS_FAILED(XRE_GetFileFromPath(greDir, getter_AddRefs(xreDir)))) {
NSLog(@"Unable to open XRE dir");
@throw MakeException(@"Error", @"Unable to open application XRE directory.");
}
xreDir.forget(&webShellAppData->xreDirectory);
NS_IF_RELEASE(webShellAppData->directory);
directory.forget(&webShellAppData->directory);
// There is only XUL.
result = XRE_main(argc, argv, webShellAppData);
XRE_FreeAppData(webShellAppData);
}
NS_LogTerm();
return result;
}
}
@catch (NSException *e) {
NSLog(@"got exception: %@", e);
DisplayErrorAlert([e name], [e reason]);
}
@finally {
[pool drain];
}
return 0;
} //end main
NSException*
MakeException(NSString* name, NSString* message)
{
NSException* myException = [NSException
exceptionWithName:name
reason:message
userInfo:nil];
return myException;
}
void
DisplayErrorAlert(NSString* title, NSString* message)
{
CFUserNotificationDisplayNotice(0, kCFUserNotificationNoteAlertLevel,
NULL, NULL, NULL,
(CFStringRef)title,
(CFStringRef)message,
CFSTR("Quit")
);
}
/* Find the currently installed Firefox, if any, and return
* an absolute path to it. may return nil */
NSString
*PathToWebRT(NSString* alternateBinaryID)
{
//default is firefox
NSString *binaryPath = nil;
//we look for these flavors of Firefox, in this order
NSArray* launchBinarySearchList = [NSArray arrayWithObjects: @"org.mozilla.nightly",
@"org.mozilla.aurora",
@"org.mozilla.firefox", nil];
//if they provided a manual override, use that. If they made an error, it will fail to launch
if (alternateBinaryID != nil && ([alternateBinaryID length] > 0)) {
binaryPath = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:alternateBinaryID];
if (binaryPath == nil || [binaryPath length] == 0) {
@throw MakeException(@"WebappRT Not Found",
[NSString stringWithFormat:@"Failed to locate specified override runtime with signature '%@'", alternateBinaryID]);
}
return binaryPath;
}
//No override found, loop through the various flavors of firefox we have
for (NSString* signature in launchBinarySearchList) {
NSLog(@"SEARCHING for webapprt, trying: %@", signature);
binaryPath = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:signature];
if (binaryPath && [binaryPath length] > 0) {
return binaryPath;
}
}
NSLog(@"unable to find a valid webrt path");
@throw MakeException(@"Missing Runtime", @"Mozilla Apps require Firefox to be installed");
return nil;
}
void
ExecNewBinary(NSString* launchPath)
{
NSLog(@" launching webrt at path: %@\n", launchPath);
const char *const newargv[] = {[launchPath UTF8String], NULL};
NSLog(@"COMMAND LINE: '%@ %s'", launchPath, newargv[0]);
execv([launchPath UTF8String], (char **)newargv);
}

13
webapprt/prefs.js Normal file
View File

@ -0,0 +1,13 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
pref("browser.chromeURL", "chrome://webapprt/content/webapp.xul");
// We set this to the value of DEFAULT_HIDDENWINDOW_URL in nsAppShellService.cpp
// so our app is treated as not having an application-provided hidden window.
// Ideally, we could just leave it out, but because we are being distributed
// in a unified directory with Firefox, Firefox's preferences are being read
// before ours, which means this preference is being set by Firefox, and we need
// to set it here to override the Firefox-provided value.
pref("browser.hiddenWindowChromeURL", "resource://gre-resources/hiddenWindow.html");

18
webapprt/webapprt.ini.in Normal file
View File

@ -0,0 +1,18 @@
#if 0
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this file,
; You can obtain one at http://mozilla.org/MPL/2.0/.
#endif
#filter substitution
[App]
ID=webapprt@mozilla.org
Vendor=Mozilla
Name=Webapp Runtime
Version=@GRE_MILESTONE@
BuildID=@GRE_BUILDID@
[Gecko]
MinVersion=@GRE_MILESTONE@
MaxVersion=@GRE_MILESTONE@

125
webapprt/win/Makefile.in Normal file
View File

@ -0,0 +1,125 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
# Build a binary bootstrapping with XRE_main
PROGRAM = webapprt-stub$(BIN_SUFFIX)
CPPSRCS = webapprt.cpp
# Don't create a dependency on mozglue, which is impossible (difficult?)
# to dynamically link into our executable, as we copy it to arbitrary locations.
MOZ_GLUE_LDFLAGS =
# mozglue uses mfbt's Assertions.cpp, which provides MOZ_ASSERT, which lots
# of code in libxpcom uses, so we have to do the same.
VPATH += $(topsrcdir)/mfbt
CPPSRCS += Assertions.cpp
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
LOCAL_INCLUDES += -I$(DEPTH)/build
DEFINES += -DXPCOM_GLUE
STL_FLAGS=
LIBS = \
$(XPCOM_STANDALONE_GLUE_LDOPTS) \
$(NULL)
ifndef MOZ_WINCONSOLE
ifdef MOZ_DEBUG
MOZ_WINCONSOLE = 1
else
MOZ_WINCONSOLE = 0
endif
endif
# Installer stuff
include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
CONFIG_DIR = instgen
SFX_MODULE = $(topsrcdir)/other-licenses/7zstub/firefox/7zSD.sfx
APP_VERSION := $(shell cat $(topsrcdir)/browser/config/version.txt)
DEFINES += -DAPP_VERSION=$(APP_VERSION)
include $(topsrcdir)/config/config.mk
ifdef _MSC_VER
# Always enter a Windows program through wmain, whether or not we're
# a console application.
WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup
endif
OS_LIBS += $(call EXPAND_LIBNAME,shell32)
RCINCLUDE = webapprt.rc
ifndef GNU_CC
RCFLAGS += -I$(srcdir)
else
RCFLAGS += --include-dir $(srcdir)
endif
ifdef DEBUG
RCFLAGS += -DDEBUG
endif
# Uninstaller
ifdef LOCALE_MERGEDIR
PPL_LOCALE_ARGS = \
--l10n-dir=$(LOCALE_MERGEDIR)/webapprt/webapp-uninstaller \
--l10n-dir=$(call EXPAND_LOCALE_SRCDIR,webapprt/locales)/webapp-uninstaller \
--l10n-dir=$(topsrcdir)/webapprt/locales/en-US/webapp-uninstaller \
$(NULL)
else
PPL_LOCALE_ARGS=$(call EXPAND_LOCALE_SRCDIR,webapprt/locales)/webapp-uninstaller
endif
libs::
$(RM) -r $(CONFIG_DIR)
$(MKDIR) $(CONFIG_DIR)
$(PYTHON) $(topsrcdir)/config/Preprocessor.py -Fsubstitution \
$(DEFINES) $(ACDEFINES) \
$(srcdir)/webapp-uninstaller.nsi.in > $(CONFIG_DIR)/webapp-uninstaller.nsi
$(PYTHON) \
$(topsrcdir)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py \
--create-nlf-file $(topsrcdir) $(AB_CD) $(CONFIG_DIR)
$(PYTHON) \
$(topsrcdir)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py \
--preprocess-single-file $(topsrcdir) $(PPL_LOCALE_ARGS) $(CONFIG_DIR) \
webapp-uninstaller.properties webapp-uninstaller-locale.nsh
$(MAKE) webapp_uninstaller
GARBAGE_DIRS += instgen
include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/makensis.mk
GRE_BUILDID := $(shell cat $(DEPTH)/config/buildid)
DEFINES += -DGRE_BUILDID=$(GRE_BUILDID)
webapprt.$(OBJ_SUFFIX): $(DEPTH)/config/buildid
# Control the default heap size.
# This is the heap returned by GetProcessHeap().
# As we use the CRT heap, the default size is too large and wastes VM.
#
# The default heap size is 1MB on Win32.
# The heap will grow if need be.
#
# Set it to 256k. See bug 127069.
#
ifndef GNU_CC
LDFLAGS += /HEAP:0x40000
ifeq ($(OS_TEST),x86_64)
# set stack to 2MB on x64 build. See bug 582910
LDFLAGS += -STACK:2097152
endif
endif

View File

@ -0,0 +1,163 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
# Required Plugins:
# ShellLink http://nsis.sourceforge.net/ShellLink_plug-in
; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs
!verbose 3
; 7-Zip provides better compression than the lzma from NSIS so we add the files
; uncompressed and let the application installer compress it.
SetDatablockOptimize on
SetCompress off
CRCCheck on
SilentInstall silent
RequestExecutionLevel user
!addplugindir ./
; prevents compiling of the reg write logging.
!define NO_LOG
; Variables
Var AppFilename
Var AppName
Var AppRTTempDir
; Variables/macros used by common.nsh
Var TmpVal
!define FileMainEXE "$AppFilename.exe"
; Other included files may depend upon these includes!
; The following includes are provided by NSIS.
!include "FileFunc.nsh"
!insertmacro GetParameters
!insertmacro un.RefreshShellIcons
!include "LogicLib.nsh"
!include "WinMessages.nsh"
!include "WinVer.nsh"
!include "WordFunc.nsh"
; File properties, version strings, etc
!define CompanyName "Mozilla Corporation"
!define UninstallerName "Mozilla Webapp Runtime App Uninstaller"
!define UninstallerFilename "webapp-uninstaller.exe"
!define AppVersion "@APP_VERSION@"
VIProductVersion "1.0.0.0"
VIAddVersionKey "ProductName" "${UninstallerName}"
VIAddVersionKey "CompanyName" "${CompanyName}"
VIAddVersionKey "LegalCopyright" "${CompanyName}"
VIAddVersionKey "FileVersion" "${AppVersion}"
VIAddVersionKey "ProductVersion" "${AppVersion}"
VIAddVersionKey "FileDescription" "${UninstallerName}"
VIAddVersionKey "OriginalFilename" "${UninstallerFilename}"
; Mozilla custom include
!include "common.nsh"
!insertmacro un.DeleteShortcuts
!insertmacro un.RegCleanUninstall
!insertmacro un.ParseUninstallLog
Name "Mozilla Web App Runtime App"
OutFile "${UninstallerFilename}"
ShowUnInstDetails nevershow
# Create a blank page so that the default pages (instfiles) don't appear
UninstPage custom un.blankPage
################################################################################
# Install Sections
# The "installer" that is generated by this file will be run during the build
# process to generate an uninstaller. We call `WriteUninstaller` during
# `onInit` so this section is empty.
Section ""
SectionEnd
################################################################################
# This is where uninstallation happens
################################################################################
Function un.blankPage
MessageBox MB_OKCANCEL "$(UN_CONFIRM_UNINSTALL)" /SD IDOK IDCANCEL done
; Delete the app exe to prevent launching the app while we are uninstalling.
ClearErrors
${DeleteFile} "$INSTDIR\${FileMainEXE}"
${If} ${Errors}
; If the app is running, rename the EXE out of the way
CreateDirectory "$AppRTTempDir"
Rename "$INSTDIR\${FileMainEXE}" "$AppRTTempDir\${FileMainEXE}"
ClearErrors
${EndIf}
SetShellVarContext current ; Set SHCTX to HKCU
; Remove our entry in the "Uninstall" key
${un.RegCleanUninstall}
; Remove our shortcuts from start menu, desktop, and taskbar
${un.DeleteShortcuts}
; Parse the uninstall log to remove all installed
; files / directories this install is responsible for.
${un.ParseUninstallLog}
; Remove the uninstall directory that we control
RmDir /r "$INSTDIR\uninstall"
; Remove the installation directory if it is empty
${RemoveDir} "$INSTDIR"
; Refresh shell icons to reflect the changes we've made
${un.RefreshShellIcons}
done:
FunctionEnd
################################################################################
# Language
!verbose push
!verbose 3
!include "webapp-uninstaller-locale.nsh"
!verbose pop
; Set this after the locale files to override it if it is in the locale. Using
; " " for BrandingText will hide the "Nullsoft Install System..." branding.
BrandingText " "
# Initialization Functions
Function .onInit
GetTempFileName $0
Delete "$0"
CreateDirectory "$0"
SetOutPath "$0"
StrCpy $1 "$0\${UninstallerFilename}"
WriteUninstaller "$1"
${GetParameters} $2
StrCpy $2 "_?=$EXEDIR $2"
Exec '"$1" $2'
Quit
FunctionEnd
Function un.onInit
StrCpy $LANGUAGE 0
${un.GetParent} "$INSTDIR" $INSTDIR
${un.GetLongPath} "$INSTDIR" $INSTDIR
ReadINIStr $AppFilename "$INSTDIR\webapp.ini" "WebappRT" "Executable"
ReadINIStr $AppName "$INSTDIR\webapp.ini" "Webapp" "Name"
${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}"
Abort
${EndUnless}
StrCpy $AppRTTempDir "$TEMP\moz_webapprt"
RmDir /r "$AppRTTempDir"
FunctionEnd

513
webapprt/win/webapprt.cpp Normal file
View File

@ -0,0 +1,513 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
// System headers (alphabetical)
#include <fcntl.h>
#include <io.h>
#include <share.h>
#include <sys/stat.h>
#include <windows.h>
// Mozilla headers (alphabetical)
#include "nsILocalFile.h"
#include "nsINIParser.h"
#include "nsWindowsWMain.cpp" // we want a wmain entry point
#include "nsXPCOMGlue.h"
#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
#include "nsXULAppAPI.h"
XRE_GetFileFromPathType XRE_GetFileFromPath;
XRE_CreateAppDataType XRE_CreateAppData;
XRE_FreeAppDataType XRE_FreeAppData;
XRE_mainType XRE_main;
namespace {
const char kAPP_INI[] = "application.ini";
const char kWEBAPP_INI[] = "webapp.ini";
const char kWEBAPPRT_INI[] = "webapprt.ini";
const char kAPP_ENV_PREFIX[] = "XUL_APP_FILE=";
const char kAPP_RT[] = "webapprt-stub.exe";
const wchar_t kAPP_RT_BACKUP[] = L"webapprt.old";
wchar_t curExePath[MAXPATHLEN];
wchar_t backupFilePath[MAXPATHLEN];
wchar_t iconPath[MAXPATHLEN];
char profile[MAXPATHLEN];
int* pargc;
char*** pargv;
// Copied from toolkit/xre/nsAppData.cpp.
void
SetAllocatedString(const char *&str, const char *newvalue)
{
NS_Free(const_cast<char*>(str));
if (newvalue) {
str = NS_strdup(newvalue);
}
else {
str = nsnull;
}
}
nsresult
joinPath(char* const dest,
char const* const dir,
char const* const leaf,
size_t bufferSize)
{
size_t dirLen = strlen(dir);
size_t leafLen = strlen(leaf);
bool needsSeparator = (dirLen != 0
&& dir[dirLen-1] != '\\'
&& leafLen != 0
&& leaf[0] != '\\');
if (dirLen + (needsSeparator? 1 : 0) + leafLen >= bufferSize) {
return NS_ERROR_FAILURE;
}
strncpy(dest, dir, bufferSize);
char* destEnd = dest + dirLen;
if (needsSeparator) {
*(destEnd++) = '\\';
}
strncpy(destEnd, leaf, leafLen);
return NS_OK;
}
/**
* A helper class which calls NS_LogInit/NS_LogTerm in its scope.
*/
class ScopedLogging
{
public:
ScopedLogging() { NS_LogInit(); }
~ScopedLogging() { NS_LogTerm(); }
};
/**
* A helper class for scope-guarding nsXREAppData.
*/
class ScopedXREAppData
{
public:
ScopedXREAppData()
: mAppData(NULL) { }
nsresult
create(nsILocalFile* aINIFile)
{
return XRE_CreateAppData(aINIFile, &mAppData);
}
~ScopedXREAppData()
{
if (NULL != mAppData) {
XRE_FreeAppData(mAppData);
}
}
nsXREAppData* const
operator->()
{
return get();
}
nsXREAppData
operator*()
{
return *get();
}
operator
nsXREAppData*()
{
return get();
}
private:
nsXREAppData* mAppData;
nsXREAppData* const get() { return mAppData; }
};
void
Output(const wchar_t *fmt, ... )
{
va_list ap;
va_start(ap, fmt);
wchar_t msg[1024];
_vsnwprintf_s(msg, _countof(msg), _countof(msg), fmt, ap);
MessageBoxW(NULL, msg, L"WebappRT", MB_OK);
va_end(ap);
}
void
Output(const char *fmt, ... )
{
va_list ap;
va_start(ap, fmt);
char msg[1024];
vsnprintf(msg, sizeof(msg), fmt, ap);
wchar_t wide_msg[1024];
MultiByteToWideChar(CP_UTF8,
0,
msg,
-1,
wide_msg,
_countof(wide_msg));
Output(wide_msg);
va_end(ap);
}
const nsDynamicFunctionLoad kXULFuncs[] = {
{ "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
{ "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
{ "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
{ "XRE_main", (NSFuncPtr*) &XRE_main },
{ nsnull, nsnull }
};
bool
AttemptCopyAndLaunch(wchar_t* src)
{
// Rename the old app executable
if (FALSE == ::MoveFileExW(curExePath,
backupFilePath,
MOVEFILE_REPLACE_EXISTING)) {
return false;
}
// Copy webapprt-stub.exe from the Firefox dir to the app's dir
if (FALSE == ::CopyFileW(src,
curExePath,
TRUE)) {
// Try to move the old file back to its original location
::MoveFileW(backupFilePath,
curExePath);
return false;
}
// XXX: We will soon embed the app's icon in the EXE here
STARTUPINFOW si;
PROCESS_INFORMATION pi;
::ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
::ZeroMemory(&pi, sizeof(pi));
if (!CreateProcessW(curExePath, // Module name
NULL, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si,
&pi)) {
return false;
}
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
return true;
}
bool
AttemptCopyAndLaunch(char* srcUtf8)
{
wchar_t src[MAXPATHLEN];
if (0 == MultiByteToWideChar(CP_UTF8,
0,
srcUtf8,
-1,
src,
MAXPATHLEN)) {
return false;
}
return AttemptCopyAndLaunch(src);
}
bool
AttemptGRELoadAndLaunch(char* greDir)
{
nsresult rv;
char xpcomDllPath[MAXPATHLEN];
rv = joinPath(xpcomDllPath, greDir, XPCOM_DLL, MAXPATHLEN);
NS_ENSURE_SUCCESS(rv, false);
rv = XPCOMGlueStartup(xpcomDllPath);
NS_ENSURE_SUCCESS(rv, false);
rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
NS_ENSURE_SUCCESS(rv, false);
// NOTE: The GRE has successfully loaded, so we can use XPCOM now
{ // Scope for any XPCOM stuff we create
ScopedLogging log;
// Get the path to the runtime's INI file. This should be in the
// same directory as the GRE.
char rtIniPath[MAXPATHLEN];
rv = joinPath(rtIniPath, greDir, kWEBAPPRT_INI, MAXPATHLEN);
NS_ENSURE_SUCCESS(rv, false);
// Load the runtime's INI from its path.
nsCOMPtr<nsILocalFile> rtINI;
rv = XRE_GetFileFromPath(rtIniPath, getter_AddRefs(rtINI));
NS_ENSURE_SUCCESS(rv, false);
if (!rtINI) {
return false;
}
ScopedXREAppData webShellAppData;
rv = webShellAppData.create(rtINI);
NS_ENSURE_SUCCESS(rv, rv);
SetAllocatedString(webShellAppData->profile, profile);
nsCOMPtr<nsILocalFile> directory;
rv = XRE_GetFileFromPath(greDir,
getter_AddRefs(directory));
NS_ENSURE_SUCCESS(rv, false);
nsCOMPtr<nsILocalFile> xreDir;
rv = XRE_GetFileFromPath(greDir,
getter_AddRefs(xreDir));
NS_ENSURE_SUCCESS(rv, false);
xreDir.forget(&webShellAppData->xreDirectory);
NS_IF_RELEASE(webShellAppData->directory);
directory.forget(&webShellAppData->directory);
// There is only XUL.
XRE_main(*pargc, *pargv, webShellAppData);
}
return true;
}
bool
AttemptLoadFromDir(char* firefoxDir)
{
nsresult rv;
// Here we're going to open Firefox's application.ini
char appIniPath[MAXPATHLEN];
rv = joinPath(appIniPath, firefoxDir, kAPP_INI, MAXPATHLEN);
NS_ENSURE_SUCCESS(rv, false);
nsINIParser parser;
rv = parser.Init(appIniPath);
NS_ENSURE_SUCCESS(rv, false);
// Get buildid of FF we're trying to load
char buildid[MAXPATHLEN]; // This isn't a path, so MAXPATHLEN doesn't
// necessarily make sense, but it's a
// convenient number to use.
rv = parser.GetString("App",
"BuildID",
buildid,
MAXPATHLEN);
NS_ENSURE_SUCCESS(rv, false);
if (0 == strcmp(buildid, NS_STRINGIFY(GRE_BUILDID))) {
return AttemptGRELoadAndLaunch(firefoxDir);
}
char webAppRTExe[MAXPATHLEN];
rv = joinPath(webAppRTExe, firefoxDir, kAPP_RT, MAXPATHLEN);
NS_ENSURE_SUCCESS(rv, false);
return AttemptCopyAndLaunch(webAppRTExe);
}
bool
GetFirefoxDirFromRegistry(char* firefoxDir)
{
HKEY key;
wchar_t wideGreDir[MAXPATHLEN];
if (ERROR_SUCCESS !=
RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows"
L"\\CurrentVersion\\App paths\\firefox.exe",
0,
KEY_READ,
&key)) {
return false;
}
DWORD length = MAXPATHLEN * sizeof(wchar_t);
// XXX: When Vista/XP64 become our minimum supported client, we can use
// RegGetValue instead
if (ERROR_SUCCESS != RegQueryValueExW(key,
L"Path",
NULL,
NULL,
reinterpret_cast<BYTE*>(wideGreDir),
&length)) {
RegCloseKey(key);
return false;
};
RegCloseKey(key);
// According to this article, we need to write our own null terminator:
// http://msdn.microsoft.com/en-us/library/ms724911%28v=vs.85%29.aspx
length = length / sizeof(wchar_t);
if (wideGreDir[length] != L'\0') {
if (length >= MAXPATHLEN) {
return false;
}
wideGreDir[length] = L'\0';
}
if (0 == WideCharToMultiByte(CP_UTF8,
0,
wideGreDir,
-1,
firefoxDir,
MAXPATHLEN,
NULL,
NULL)) {
return false;
}
return true;
}
};
//////////////////////////////////////////////////////////////////////////////
// main
//
// Note: XPCOM cannot be used until AttemptGRELoad has returned successfully.
int
main(int argc, char* argv[])
{
pargc = &argc;
pargv = &argv;
nsresult rv;
char buffer[MAXPATHLEN];
wchar_t wbuffer[MAXPATHLEN];
// Set up curEXEPath
if (!GetModuleFileNameW(0, wbuffer, MAXPATHLEN)) {
Output("Couldn't calculate the application directory.");
return 255;
}
wcsncpy(curExePath, wbuffer, MAXPATHLEN);
// Get the current directory into wbuffer
wchar_t* lastSlash = wcsrchr(wbuffer, L'\\');
if (!lastSlash) {
Output("Application directory format not understood.");
return 255;
}
*(++lastSlash) = L'\0';
// Set up backup file path
if (wcslen(wbuffer) + _countof(kAPP_RT_BACKUP) >= MAXPATHLEN) {
Output("Application directory path is too long (couldn't set up backup file path).");
}
wcsncpy(lastSlash, kAPP_RT_BACKUP, _countof(kAPP_RT_BACKUP));
wcsncpy(backupFilePath, wbuffer, MAXPATHLEN);
*lastSlash = L'\0';
// Convert current directory to utf8 and stuff it in buffer
if (0 == WideCharToMultiByte(CP_UTF8,
0,
wbuffer,
-1,
buffer,
MAXPATHLEN,
NULL,
NULL)) {
Output("Application directory could not be processed.");
return 255;
}
// Set up appIniPath with path to webapp.ini.
// This should be in the same directory as the running executable.
char appIniPath[MAXPATHLEN];
if (NS_FAILED(joinPath(appIniPath, buffer, kWEBAPP_INI, MAXPATHLEN))) {
Output("Path to webapp.ini could not be processed.");
return 255;
}
// Open webapp.ini as an INI file (as opposed to using the
// XRE webapp.ini-specific processing we do later)
nsINIParser parser;
if (NS_FAILED(parser.Init(appIniPath))) {
Output("Could not open webapp.ini");
return 255;
}
// Set up our environment to know where webapp.ini was loaded from.
char appEnv[MAXPATHLEN + _countof(kAPP_ENV_PREFIX)];
strcpy(appEnv, kAPP_ENV_PREFIX);
strcpy(appEnv + _countof(kAPP_ENV_PREFIX) - 1, appIniPath);
if (putenv(appEnv)) {
Output("Couldn't set up app environment");
return 255;
}
// Get profile dir from webapp.ini
if (NS_FAILED(parser.GetString("Webapp",
"Profile",
profile,
MAXPATHLEN))) {
Output("Unable to retrieve profile from web app INI file");
return 255;
}
char firefoxDir[MAXPATHLEN];
// First attempt at loading Firefox binaries:
// Get the location of Firefox from our webapp.ini
// XXX: This string better be UTF-8...
rv = parser.GetString("WebappRT",
"InstallDir",
firefoxDir,
MAXPATHLEN);
if (NS_SUCCEEDED(rv)) {
if (AttemptLoadFromDir(firefoxDir)) {
return 0;
}
}
// Second attempt at loading Firefox binaries:
// Get the location of Firefox from the registry
rv = GetFirefoxDirFromRegistry(firefoxDir);
if (NS_SUCCEEDED(rv)) {
if (AttemptLoadFromDir(firefoxDir)) {
// XXX: Write gre dir location to webapp.ini
return 0;
}
}
// We've done all we know how to do to try to find and launch FF
Output("This app requires that Firefox version 14 or above is installed."
" Firefox 14+ has not been detected.");
return 255;
}

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="*"
name="Mozilla.WebAppRT"
type="win32"
/>
<description>Mozilla Webapp Runtime</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
<ms_asmv3:security>
<ms_asmv3:requestedPrivileges>
<ms_asmv3:requestedExecutionLevel level="asInvoker" uiAccess="false" />
</ms_asmv3:requestedPrivileges>
</ms_asmv3:security>
</ms_asmv3:trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
</application>
</compatibility>
</assembly>

6
webapprt/win/webapprt.rc Normal file
View File

@ -0,0 +1,6 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
1 24 "webapprt.exe.manifest"

View File

@ -40,6 +40,8 @@
#ifndef mozilla_FileUtils_h #ifndef mozilla_FileUtils_h
#define mozilla_FileUtils_h #define mozilla_FileUtils_h
#include "nscore.h" // nsnull
#if defined(XP_UNIX) || defined(XP_OS2) #if defined(XP_UNIX) || defined(XP_OS2)
# include <unistd.h> # include <unistd.h>
#elif defined(XP_WIN) #elif defined(XP_WIN)

View File

@ -121,8 +121,22 @@ nsAppShellService::CreateHiddenWindow()
PRUint32 chromeMask = 0; PRUint32 chromeMask = 0;
nsAdoptingCString prefVal = nsAdoptingCString prefVal =
Preferences::GetCString("browser.hiddenWindowChromeURL"); Preferences::GetCString("browser.hiddenWindowChromeURL");
const char* hiddenWindowURL = prefVal.get() ? prefVal.get() : DEFAULT_HIDDENWINDOW_URL;
mApplicationProvidedHiddenWindow = prefVal.get() ? true : false; // Set mApplicationProvidedHiddenWindow to true only if there is a hidden
// window chrome URL in preferences AND it is set to a non-default value.
// This enables an app that doesn't have a hidden window (like WebappRT)
// to share an app directory with one that does (like Firefox), the former
// taking advantage of this behavior to "unset" the latter's hidden window
// pref by setting it to the default value.
//
// (Ideally, the former would be able to simply unset the latter's pref,
// but there is no way to do that; even more ideally, the two apps would not
// share an app directory, but in the case of WebappRT and Firefox that's
// a longer-term fix.)
//
mApplicationProvidedHiddenWindow = prefVal.get() && strcmp(prefVal.get(), DEFAULT_HIDDENWINDOW_URL) ? true : false;
const char* hiddenWindowURL = mApplicationProvidedHiddenWindow ? prefVal.get() : DEFAULT_HIDDENWINDOW_URL;
#else #else
static const char hiddenWindowURL[] = DEFAULT_HIDDENWINDOW_URL; static const char hiddenWindowURL[] = DEFAULT_HIDDENWINDOW_URL;
PRUint32 chromeMask = nsIWebBrowserChrome::CHROME_ALL; PRUint32 chromeMask = nsIWebBrowserChrome::CHROME_ALL;