зеркало из https://github.com/mozilla/gecko-dev.git
Bug 745018. Implement webapp runtime for Linux. r=jst
This commit is contained in:
Родитель
fdedcd5b54
Коммит
0f5bf85e2d
|
@ -15,10 +15,6 @@ if test "$OS_ARCH" = "WINNT"; then
|
|||
fi
|
||||
fi
|
||||
|
||||
if (test "$OS_TARGET" = "WINNT" -o "$OS_TARGET" = "Darwin"); then
|
||||
MOZ_WEBAPP_RUNTIME=1
|
||||
fi
|
||||
|
||||
MOZ_CHROME_FILE_FORMAT=omni
|
||||
MOZ_SAFE_BROWSING=1
|
||||
MOZ_SERVICES_SYNC=1
|
||||
|
@ -44,3 +40,4 @@ MAR_CHANNEL_ID=firefox-mozilla-central
|
|||
MOZ_PROFILE_MIGRATOR=1
|
||||
MOZ_EXTENSION_MANAGER=1
|
||||
MOZ_APP_STATIC_INI=1
|
||||
MOZ_WEBAPP_RUNTIME=1
|
||||
|
|
|
@ -6413,6 +6413,9 @@ MOZ_ARG_DISABLE_BOOL(webapp-runtime,
|
|||
[ --disable-webapp-runtime Disable Web App Runtime],
|
||||
MOZ_WEBAPP_RUNTIME=,
|
||||
MOZ_WEBAPP_RUNTIME=1)
|
||||
if test "$MOZ_WIDGET_TOOLKIT" != "windows" -a "$MOZ_WIDGET_TOOLKIT" != "cocoa" -a "$MOZ_WIDGET_TOOLKIT" != "gtk2"; then
|
||||
MOZ_WEBAPP_RUNTIME=
|
||||
fi
|
||||
if test "$OS_ARCH" = "WINNT" -a -z "$MAKENSISU" -a -n "$CROSS_COMPILE"; then
|
||||
MOZ_WEBAPP_RUNTIME=
|
||||
fi
|
||||
|
|
|
@ -23,6 +23,10 @@ DIRS += win
|
|||
else
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
DIRS += mac
|
||||
else
|
||||
ifeq ($(OS_ARCH),Linux)
|
||||
DIRS += linux
|
||||
endif # linux
|
||||
endif # mac
|
||||
endif # windows
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# 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
|
||||
|
||||
CPPSRCS = webapprt.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) \
|
||||
$(MOZ_GTK2_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CXXFLAGS += \
|
||||
$(MOZ_GTK2_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
GRE_BUILDID := $(shell cat $(DEPTH)/config/buildid)
|
||||
DEFINES += -DGRE_BUILDID=$(GRE_BUILDID)
|
||||
|
||||
webapprt.$(OBJ_SUFFIX): $(DEPTH)/config/buildid
|
|
@ -0,0 +1,289 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
// GTK headers
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
// Linux headers
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Mozilla headers
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsINIParser.h"
|
||||
#include "nsXPCOMGlue.h"
|
||||
#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
const char kAPP_INI[] = "application.ini";
|
||||
const char kWEBAPP_INI[] = "webapp.ini";
|
||||
const char kWEBAPPRT_INI[] = "webapprt.ini";
|
||||
const char kWEBAPPRT_PATH[] = "webapprt";
|
||||
const char kAPP_ENV_VAR[] = "XUL_APP_FILE";
|
||||
const char kAPP_RT[] = "webapprt-stub";
|
||||
|
||||
int* pargc;
|
||||
char*** pargv;
|
||||
|
||||
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 }
|
||||
};
|
||||
|
||||
class ScopedLogging
|
||||
{
|
||||
public:
|
||||
ScopedLogging() { NS_LogInit(); }
|
||||
~ScopedLogging() { NS_LogTerm(); }
|
||||
};
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to open a dialog box displaying the message provided
|
||||
void ErrorDialog(const char* message)
|
||||
{
|
||||
GtkWidget* dialog;
|
||||
|
||||
dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", message);
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
// Function to get the parent dir of a file
|
||||
void GetDirFromPath(char* parentDir, char* filePath)
|
||||
{
|
||||
char* base = strrchr(filePath, '/');
|
||||
|
||||
if (!base) {
|
||||
strcpy(parentDir, ".");
|
||||
}
|
||||
else {
|
||||
while (base > filePath && *base == '/')
|
||||
base--;
|
||||
|
||||
int len = 1 + base - filePath;
|
||||
strncpy(parentDir, filePath, len);
|
||||
parentDir[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
bool CopyFile(const char* inputFile, const char* outputFile)
|
||||
{
|
||||
// Open input file
|
||||
int inputFD = open(inputFile, O_RDONLY);
|
||||
if (!inputFD)
|
||||
return false;
|
||||
|
||||
// Open output file
|
||||
int outputFD = creat(outputFile, S_IRWXU);
|
||||
if (!outputFD)
|
||||
return false;
|
||||
|
||||
// Copy file
|
||||
char buf[BUFSIZ];
|
||||
ssize_t bytesRead;
|
||||
|
||||
while ((bytesRead = read(inputFD, buf, BUFSIZ)) > 0) {
|
||||
ssize_t bytesWritten = write(outputFD, buf, bytesRead);
|
||||
if (bytesWritten < 0) {
|
||||
bytesRead = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Close file descriptors
|
||||
close(inputFD);
|
||||
close(outputFD);
|
||||
|
||||
return (bytesRead >= 0);
|
||||
}
|
||||
|
||||
bool GRELoadAndLaunch(const char* firefoxDir, const char* profile)
|
||||
{
|
||||
char xpcomDllPath[MAXPATHLEN];
|
||||
snprintf(xpcomDllPath, MAXPATHLEN, "%s/%s", firefoxDir, XPCOM_DLL);
|
||||
|
||||
if (NS_FAILED(XPCOMGlueStartup(xpcomDllPath))) {
|
||||
ErrorDialog("Couldn't load the XPCOM library");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NS_FAILED(XPCOMGlueLoadXULFunctions(kXULFuncs))) {
|
||||
ErrorDialog("Couldn't load libxul");
|
||||
return 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
|
||||
char rtPath[MAXPATHLEN];
|
||||
snprintf(rtPath, MAXPATHLEN, "%s/%s", firefoxDir, kWEBAPPRT_PATH);
|
||||
|
||||
// Get the path to the runtime's INI file
|
||||
char rtIniPath[MAXPATHLEN];
|
||||
snprintf(rtIniPath, MAXPATHLEN, "%s/%s", rtPath, kWEBAPPRT_INI);
|
||||
|
||||
// Load the runtime's INI from its path
|
||||
nsCOMPtr<nsILocalFile> rtINI;
|
||||
if (NS_FAILED(XRE_GetFileFromPath(rtIniPath, getter_AddRefs(rtINI)))) {
|
||||
ErrorDialog("Couldn't load the runtime INI");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exists;
|
||||
nsresult rv = rtINI->Exists(&exists);
|
||||
if (NS_FAILED(rv) || !exists) {
|
||||
ErrorDialog("The runtime INI doesn't exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsXREAppData *webShellAppData;
|
||||
if (NS_FAILED(XRE_CreateAppData(rtINI, &webShellAppData))) {
|
||||
ErrorDialog("Couldn't read WebappRT application.ini");
|
||||
return false;
|
||||
}
|
||||
|
||||
SetAllocatedString(webShellAppData->profile, profile);
|
||||
|
||||
nsCOMPtr<nsILocalFile> directory;
|
||||
if (NS_FAILED(XRE_GetFileFromPath(rtPath, getter_AddRefs(directory)))) {
|
||||
ErrorDialog("Couldn't open runtime directory");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILocalFile> xreDir;
|
||||
if (NS_FAILED(XRE_GetFileFromPath(firefoxDir, getter_AddRefs(xreDir)))) {
|
||||
ErrorDialog("Couldn't open XRE directory");
|
||||
return false;
|
||||
}
|
||||
|
||||
xreDir.forget(&webShellAppData->xreDirectory);
|
||||
NS_IF_RELEASE(webShellAppData->directory);
|
||||
directory.forget(&webShellAppData->directory);
|
||||
|
||||
XRE_main(*pargc, *pargv, webShellAppData, 0);
|
||||
|
||||
XRE_FreeAppData(webShellAppData);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CopyAndRelaunch(const char* firefoxDir, const char* curExePath)
|
||||
{
|
||||
char newExePath[MAXPATHLEN];
|
||||
snprintf(newExePath, MAXPATHLEN, "%s/%s", firefoxDir, kAPP_RT);
|
||||
|
||||
if (unlink(curExePath) == -1) {
|
||||
ErrorDialog("Couldn't remove the old webapprt-stub executable");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CopyFile(newExePath, curExePath)) {
|
||||
ErrorDialog("Couldn't copy the new webapprt-stub executable");
|
||||
return;
|
||||
}
|
||||
|
||||
execv(curExePath, *pargv);
|
||||
|
||||
ErrorDialog("Couldn't execute the new webapprt-stub executable");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
pargc = &argc;
|
||||
pargv = &argv;
|
||||
|
||||
// Get current executable path
|
||||
char curExePath[MAXPATHLEN];
|
||||
if (readlink("/proc/self/exe", curExePath, MAXPATHLEN) == -1) {
|
||||
ErrorDialog("Couldn't read current executable path");
|
||||
return 255;
|
||||
}
|
||||
|
||||
// Set up webAppIniPath with path to webapp.ini
|
||||
char curExeDir[MAXPATHLEN];
|
||||
GetDirFromPath(curExeDir, curExePath);
|
||||
char webAppIniPath[MAXPATHLEN];
|
||||
snprintf(webAppIniPath, MAXPATHLEN, "%s/%s", curExeDir, kWEBAPP_INI);
|
||||
|
||||
// Open webapp.ini as an INI file
|
||||
nsINIParser parser;
|
||||
if (NS_FAILED(parser.Init(webAppIniPath))) {
|
||||
ErrorDialog("Couldn't open webapp.ini");
|
||||
return 255;
|
||||
}
|
||||
|
||||
// Set up our environment to know where webapp.ini was loaded from
|
||||
if (setenv(kAPP_ENV_VAR, webAppIniPath, 1) == -1) {
|
||||
ErrorDialog("Couldn't set up app environment");
|
||||
return 255;
|
||||
}
|
||||
|
||||
// Get profile dir from webapp.ini
|
||||
char profile[MAXPATHLEN];
|
||||
if (NS_FAILED(parser.GetString("Webapp", "Profile", profile, MAXPATHLEN))) {
|
||||
ErrorDialog("Couldn't retrieve profile from web app INI file");
|
||||
return 255;
|
||||
}
|
||||
|
||||
// Get the location of Firefox from our webapp.ini
|
||||
char firefoxDir[MAXPATHLEN];
|
||||
if (NS_FAILED(parser.GetString("WebappRT", "InstallDir", firefoxDir, MAXPATHLEN))) {
|
||||
ErrorDialog("Couldn't find your Firefox install directory.");
|
||||
return 255;
|
||||
}
|
||||
|
||||
// Set up appIniPath with path to application.ini.
|
||||
// This is in the Firefox installation directory.
|
||||
char appIniPath[MAXPATHLEN];
|
||||
snprintf(appIniPath, MAXPATHLEN, "%s/%s", firefoxDir, kAPP_INI);
|
||||
|
||||
if (NS_FAILED(parser.Init(appIniPath))) {
|
||||
ErrorDialog("Couldn't open Firefox application.ini");
|
||||
return 255;
|
||||
}
|
||||
|
||||
// Get buildid of Firefox we're trying to load (MAXPATHLEN only for convenience)
|
||||
char buildid[MAXPATHLEN];
|
||||
if (NS_FAILED(parser.GetString("App", "BuildID", buildid, MAXPATHLEN))) {
|
||||
ErrorDialog("Couldn't read BuildID from Firefox application.ini");
|
||||
return 255;
|
||||
}
|
||||
|
||||
// If WebAppRT version == Firefox version, load XUL and execute the application
|
||||
if (!strcmp(buildid, NS_STRINGIFY(GRE_BUILDID))) {
|
||||
if (GRELoadAndLaunch(firefoxDir, profile))
|
||||
return 0;
|
||||
}
|
||||
// Else, copy WebAppRT from Firefox installation and re-execute the process
|
||||
else
|
||||
CopyAndRelaunch(firefoxDir, curExePath);
|
||||
|
||||
return 255;
|
||||
}
|
Загрузка…
Ссылка в новой задаче