xulrunner/app/nsXULRunnerApp.cpp

branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
equal deleted inserted replaced
-1:000000000000 0:5c2edf66fdde
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "nsXULAppAPI.h"
6 #include "nsXPCOMGlue.h"
7 #include <stdio.h>
8 #include <stdlib.h>
9 #ifdef XP_WIN
10 #include <windows.h>
11 #define snprintf _snprintf
12 #define strcasecmp _stricmp
13 #endif
14
15 #include "nsAppRunner.h"
16 #include "nsIFile.h"
17 #include "nsCOMPtr.h"
18 #include "nsMemory.h"
19 #include "nsCRTGlue.h"
20 #include "nsStringAPI.h"
21 #include "nsServiceManagerUtils.h"
22 #include "plstr.h"
23 #include "prprf.h"
24 #include "prenv.h"
25 #include "nsINIParser.h"
26
27 #ifdef XP_WIN
28 #include "nsWindowsWMain.cpp"
29 #endif
30
31 #include "BinaryPath.h"
32
33 #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
34
35 using namespace mozilla;
36
37 /**
38 * Output a string to the user. This method is really only meant to be used to
39 * output last-ditch error messages designed for developers NOT END USERS.
40 *
41 * @param isError
42 * Pass true to indicate severe errors.
43 * @param fmt
44 * printf-style format string followed by arguments.
45 */
46 static void Output(bool isError, const char *fmt, ... )
47 {
48 va_list ap;
49 va_start(ap, fmt);
50
51 #if (defined(XP_WIN) && !MOZ_WINCONSOLE)
52 char16_t msg[2048];
53 _vsnwprintf(msg, sizeof(msg)/sizeof(msg[0]), NS_ConvertUTF8toUTF16(fmt).get(), ap);
54
55 UINT flags = MB_OK;
56 if (isError)
57 flags |= MB_ICONERROR;
58 else
59 flags |= MB_ICONINFORMATION;
60
61 MessageBoxW(nullptr, msg, L"XULRunner", flags);
62 #else
63 vfprintf(stderr, fmt, ap);
64 #endif
65
66 va_end(ap);
67 }
68
69 /**
70 * Return true if |arg| matches the given argument name.
71 */
72 static bool IsArg(const char* arg, const char* s)
73 {
74 if (*arg == '-')
75 {
76 if (*++arg == '-')
77 ++arg;
78 return !strcasecmp(arg, s);
79 }
80
81 #if defined(XP_WIN)
82 if (*arg == '/')
83 return !strcasecmp(++arg, s);
84 #endif
85
86 return false;
87 }
88
89 static nsresult
90 GetGREVersion(const char *argv0,
91 nsACString *aMilestone,
92 nsACString *aVersion)
93 {
94 if (aMilestone)
95 aMilestone->Assign("<Error>");
96 if (aVersion)
97 aVersion->Assign("<Error>");
98
99 nsCOMPtr<nsIFile> iniFile;
100 nsresult rv = BinaryPath::GetFile(argv0, getter_AddRefs(iniFile));
101 if (NS_FAILED(rv))
102 return rv;
103
104 iniFile->SetNativeLeafName(NS_LITERAL_CSTRING("platform.ini"));
105
106 nsINIParser parser;
107 rv = parser.Init(iniFile);
108 if (NS_FAILED(rv))
109 return rv;
110
111 if (aMilestone) {
112 rv = parser.GetString("Build", "Milestone", *aMilestone);
113 if (NS_FAILED(rv))
114 return rv;
115 }
116 if (aVersion) {
117 rv = parser.GetString("Build", "BuildID", *aVersion);
118 if (NS_FAILED(rv))
119 return rv;
120 }
121 return NS_OK;
122 }
123
124 /**
125 * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
126 */
127 class ScopedLogging
128 {
129 public:
130 ScopedLogging() { NS_LogInit(); }
131 ~ScopedLogging() { NS_LogTerm(); }
132 };
133
134 static void Usage(const char *argv0)
135 {
136 nsAutoCString milestone;
137 GetGREVersion(argv0, &milestone, nullptr);
138
139 // display additional information (XXX make localizable?)
140 Output(false,
141 "Mozilla XULRunner %s\n\n"
142 "Usage: " XULRUNNER_PROGNAME " [OPTIONS]\n"
143 " " XULRUNNER_PROGNAME " APP-FILE [APP-OPTIONS...]\n"
144 "\n"
145 "OPTIONS\n"
146 " --app specify APP-FILE (optional)\n"
147 " -h, --help show this message\n"
148 " -v, --version show version\n"
149 " --gre-version print the GRE version string on stdout\n"
150 "\n"
151 "APP-FILE\n"
152 " Application initialization file.\n"
153 "\n"
154 "APP-OPTIONS\n"
155 " Application specific options.\n",
156 milestone.get());
157 }
158
159 XRE_GetFileFromPathType XRE_GetFileFromPath;
160 XRE_CreateAppDataType XRE_CreateAppData;
161 XRE_FreeAppDataType XRE_FreeAppData;
162 XRE_mainType XRE_main;
163
164 static const nsDynamicFunctionLoad kXULFuncs[] = {
165 { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
166 { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
167 { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
168 { "XRE_main", (NSFuncPtr*) &XRE_main },
169 { nullptr, nullptr }
170 };
171
172 class AutoAppData
173 {
174 public:
175 AutoAppData(nsIFile* aINIFile) : mAppData(nullptr) {
176 nsresult rv = XRE_CreateAppData(aINIFile, &mAppData);
177 if (NS_FAILED(rv))
178 mAppData = nullptr;
179 }
180 ~AutoAppData() {
181 if (mAppData)
182 XRE_FreeAppData(mAppData);
183 }
184
185 operator nsXREAppData*() const { return mAppData; }
186 nsXREAppData* operator -> () const { return mAppData; }
187
188 private:
189 nsXREAppData* mAppData;
190 };
191
192 int main(int argc, char* argv[])
193 {
194 char exePath[MAXPATHLEN];
195 nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
196 if (NS_FAILED(rv)) {
197 Output(true, "Couldn't calculate the application directory.\n");
198 return 255;
199 }
200
201 char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
202 if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
203 return 255;
204
205 strcpy(++lastSlash, XPCOM_DLL);
206
207 rv = XPCOMGlueStartup(exePath);
208 if (NS_FAILED(rv)) {
209 Output(true, "Couldn't load XPCOM.\n");
210 return 255;
211 }
212
213 ScopedLogging log;
214
215 if (argc > 1 && (IsArg(argv[1], "h") ||
216 IsArg(argv[1], "help") ||
217 IsArg(argv[1], "?")))
218 {
219 Usage(argv[0]);
220 return 0;
221 }
222
223 if (argc == 2 && (IsArg(argv[1], "v") || IsArg(argv[1], "version")))
224 {
225 nsAutoCString milestone;
226 nsAutoCString version;
227 GetGREVersion(argv[0], &milestone, &version);
228 Output(false, "Mozilla XULRunner %s - %s\n",
229 milestone.get(), version.get());
230 return 0;
231 }
232
233 rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
234 if (NS_FAILED(rv)) {
235 Output(true, "Couldn't load XRE functions.\n");
236 return 255;
237 }
238
239 if (argc > 1) {
240 nsAutoCString milestone;
241 rv = GetGREVersion(argv[0], &milestone, nullptr);
242 if (NS_FAILED(rv))
243 return 2;
244
245 if (IsArg(argv[1], "gre-version")) {
246 if (argc != 2) {
247 Usage(argv[0]);
248 return 1;
249 }
250
251 printf("%s\n", milestone.get());
252 return 0;
253 }
254
255 if (IsArg(argv[1], "install-app")) {
256 Output(true, "--install-app support has been removed. Use 'python install-app.py' instead.\n");
257 return 1;
258 }
259 }
260
261 const char *appDataFile = getenv("XUL_APP_FILE");
262
263 if (!(appDataFile && *appDataFile)) {
264 if (argc < 2) {
265 Usage(argv[0]);
266 return 1;
267 }
268
269 if (IsArg(argv[1], "app")) {
270 if (argc == 2) {
271 Usage(argv[0]);
272 return 1;
273 }
274 argv[1] = argv[0];
275 ++argv;
276 --argc;
277 }
278
279 appDataFile = argv[1];
280 argv[1] = argv[0];
281 ++argv;
282 --argc;
283
284 static char kAppEnv[MAXPATHLEN];
285 snprintf(kAppEnv, MAXPATHLEN, "XUL_APP_FILE=%s", appDataFile);
286 putenv(kAppEnv);
287 }
288
289 nsCOMPtr<nsIFile> appDataLF;
290 rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appDataLF));
291 if (NS_FAILED(rv)) {
292 Output(true, "Error: unrecognized application.ini path.\n");
293 return 2;
294 }
295
296 AutoAppData appData(appDataLF);
297 if (!appData) {
298 Output(true, "Error: couldn't parse application.ini.\n");
299 return 2;
300 }
301
302 return XRE_main(argc, argv, appData, 0);
303 }

mercurial