Bug 594821 - Trigger a sync paint on intial window show. r=roc, a=final.
[mozilla-central.git] / xulrunner / app / nsXULRunnerApp.cpp
blob21670d9a2ee52d89fc96b539b47511bc844e06a4
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is Mozilla.
16 * The Initial Developer of the Original Code is IBM Corporation.
17 * Portions created by IBM Corporation are Copyright (C) 2003
18 * IBM Corporation. All Rights Reserved.
20 * Contributor(s):
21 * Darin Fisher <darin@meer.net>
22 * Benjamin Smedberg <benjamin@smedbergs.us>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include <stdio.h>
39 #include <stdlib.h>
40 #ifdef XP_WIN
41 #include <windows.h>
42 #endif
44 #include "nsXULAppAPI.h"
45 #include "nsXPCOMGlue.h"
46 #include "nsRegisterGRE.h"
47 #include "nsAppRunner.h"
48 #include "nsILocalFile.h"
49 #include "nsIXULAppInstall.h"
50 #include "nsCOMPtr.h"
51 #include "nsMemory.h"
52 #include "nsCRTGlue.h"
53 #include "nsStringAPI.h"
54 #include "nsServiceManagerUtils.h"
55 #include "plstr.h"
56 #include "prprf.h"
57 #include "prenv.h"
58 #include "nsINIParser.h"
60 #ifdef XP_WIN
61 #include "nsWindowsWMain.cpp"
62 #endif
64 /**
65 * Output a string to the user. This method is really only meant to be used to
66 * output last-ditch error messages designed for developers NOT END USERS.
68 * @param isError
69 * Pass true to indicate severe errors.
70 * @param fmt
71 * printf-style format string followed by arguments.
73 static void Output(PRBool isError, const char *fmt, ... )
75 va_list ap;
76 va_start(ap, fmt);
78 #if (defined(XP_WIN) && !MOZ_WINCONSOLE) || defined(WINCE)
79 char *msg = PR_vsmprintf(fmt, ap);
80 if (msg)
82 UINT flags = MB_OK;
83 if (isError)
84 flags |= MB_ICONERROR;
85 else
86 flags |= MB_ICONINFORMATION;
88 wchar_t wide_msg[1024];
89 MultiByteToWideChar(CP_ACP,
91 msg,
92 -1,
93 wide_msg,
94 sizeof(wide_msg) / sizeof(wchar_t));
96 MessageBoxW(NULL, wide_msg, L"XULRunner", flags);
98 PR_smprintf_free(msg);
100 #else
101 vfprintf(stderr, fmt, ap);
102 #endif
104 va_end(ap);
108 * Return true if |arg| matches the given argument name.
110 static PRBool IsArg(const char* arg, const char* s)
112 if (*arg == '-')
114 if (*++arg == '-')
115 ++arg;
116 return !PL_strcasecmp(arg, s);
119 #if defined(XP_WIN) || defined(XP_OS2)
120 if (*arg == '/')
121 return !PL_strcasecmp(++arg, s);
122 #endif
124 return PR_FALSE;
127 static nsresult
128 GetGREVersion(const char *argv0,
129 nsACString *aMilestone,
130 nsACString *aVersion)
132 if (aMilestone)
133 aMilestone->Assign("<Error>");
134 if (aVersion)
135 aVersion->Assign("<Error>");
137 nsCOMPtr<nsILocalFile> iniFile;
138 nsresult rv = XRE_GetBinaryPath(argv0, getter_AddRefs(iniFile));
139 if (NS_FAILED(rv))
140 return rv;
142 iniFile->SetNativeLeafName(NS_LITERAL_CSTRING("platform.ini"));
144 nsINIParser parser;
145 rv = parser.Init(iniFile);
146 if (NS_FAILED(rv))
147 return rv;
149 if (aMilestone) {
150 rv = parser.GetString("Build", "Milestone", *aMilestone);
151 if (NS_FAILED(rv))
152 return rv;
154 if (aVersion) {
155 rv = parser.GetString("Build", "BuildID", *aVersion);
156 if (NS_FAILED(rv))
157 return rv;
159 return NS_OK;
162 static void Usage(const char *argv0)
164 nsCAutoString milestone;
165 GetGREVersion(argv0, &milestone, nsnull);
167 // display additional information (XXX make localizable?)
168 Output(PR_FALSE,
169 "Mozilla XULRunner %s\n\n"
170 "Usage: " XULRUNNER_PROGNAME " [OPTIONS]\n"
171 " " XULRUNNER_PROGNAME " APP-FILE [APP-OPTIONS...]\n"
172 "\n"
173 "OPTIONS\n"
174 " --app specify APP-FILE (optional)\n"
175 " -h, --help show this message\n"
176 " -v, --version show version\n"
177 " --gre-version print the GRE version string on stdout\n"
178 " --register-global register this GRE in the machine registry\n"
179 " --register-user register this GRE in the user registry\n"
180 " --unregister-global unregister this GRE formerly registered with\n"
181 " --register-global\n"
182 " --unregister-user unregister this GRE formely registered with\n"
183 " --register-user\n"
184 " --find-gre <version> Find a GRE with version <version> and print\n"
185 " the path on stdout\n"
186 " --install-app <application> [<destination> [<directoryname>]]\n"
187 " Install a XUL application.\n"
188 "\n"
189 "APP-FILE\n"
190 " Application initialization file.\n"
191 "\n"
192 "APP-OPTIONS\n"
193 " Application specific options.\n",
194 milestone.get());
197 static nsresult
198 GetXULRunnerDir(const char *argv0, nsIFile* *aResult)
200 nsresult rv;
202 nsCOMPtr<nsILocalFile> appFile;
203 rv = XRE_GetBinaryPath(argv0, getter_AddRefs(appFile));
204 if (NS_FAILED(rv)) {
205 Output(PR_TRUE, "Could not find XULRunner application path.\n");
206 return rv;
209 rv = appFile->GetParent(aResult);
210 if (NS_FAILED(rv)) {
211 Output(PR_TRUE, "Could not find XULRunner installation dir.\n");
213 return rv;
216 static int
217 InstallXULApp(nsIFile* aXULRunnerDir,
218 const char *aAppLocation,
219 const char *aInstallTo,
220 const char *aLeafName)
222 nsCOMPtr<nsILocalFile> appLocation;
223 nsCOMPtr<nsILocalFile> installTo;
224 nsString leafName;
226 nsresult rv = XRE_GetFileFromPath(aAppLocation, getter_AddRefs(appLocation));
227 if (NS_FAILED(rv))
228 return 2;
230 if (aInstallTo) {
231 rv = XRE_GetFileFromPath(aInstallTo, getter_AddRefs(installTo));
232 if (NS_FAILED(rv))
233 return 2;
236 if (aLeafName)
237 NS_CStringToUTF16(nsDependentCString(aLeafName),
238 NS_CSTRING_ENCODING_NATIVE_FILESYSTEM, leafName);
240 rv = NS_InitXPCOM2(nsnull, aXULRunnerDir, nsnull);
241 if (NS_FAILED(rv))
242 return 3;
245 // Scope our COMPtr to avoid holding XPCOM refs beyond xpcom shutdown
246 nsCOMPtr<nsIXULAppInstall> install
247 (do_GetService("@mozilla.org/xulrunner/app-install-service;1"));
248 if (!install) {
249 rv = NS_ERROR_FAILURE;
251 else {
252 rv = install->InstallApplication(appLocation, installTo, leafName);
256 NS_ShutdownXPCOM(nsnull);
258 if (NS_FAILED(rv))
259 return 3;
261 return 0;
264 static const GREProperty kGREProperties[] = {
265 { "xulrunner", "true" }
266 #ifdef TARGET_XPCOM_ABI
267 , { "abi", TARGET_XPCOM_ABI }
268 #endif
269 #ifdef MOZ_JAVAXPCOM
270 , { "javaxpcom", "1" }
271 #endif
274 class AutoAppData
276 public:
277 AutoAppData(nsILocalFile* aINIFile) : mAppData(nsnull) {
278 nsresult rv = XRE_CreateAppData(aINIFile, &mAppData);
279 if (NS_FAILED(rv))
280 mAppData = nsnull;
282 ~AutoAppData() {
283 if (mAppData)
284 XRE_FreeAppData(mAppData);
287 operator nsXREAppData*() const { return mAppData; }
288 nsXREAppData* operator -> () const { return mAppData; }
290 private:
291 nsXREAppData* mAppData;
294 int main(int argc, char* argv[])
296 if (argc > 1 && (IsArg(argv[1], "h") ||
297 IsArg(argv[1], "help") ||
298 IsArg(argv[1], "?")))
300 Usage(argv[0]);
301 return 0;
304 if (argc == 2 && (IsArg(argv[1], "v") || IsArg(argv[1], "version")))
306 nsCAutoString milestone;
307 nsCAutoString version;
308 GetGREVersion(argv[0], &milestone, &version);
309 Output(PR_FALSE, "Mozilla XULRunner %s - %s\n",
310 milestone.get(), version.get());
311 return 0;
314 if (argc > 1) {
315 nsCAutoString milestone;
316 nsresult rv = GetGREVersion(argv[0], &milestone, nsnull);
317 if (NS_FAILED(rv))
318 return 2;
320 PRBool registerGlobal = IsArg(argv[1], "register-global");
321 PRBool registerUser = IsArg(argv[1], "register-user");
322 if (registerGlobal || registerUser) {
323 if (argc != 2) {
324 Usage(argv[0]);
325 return 1;
328 nsCOMPtr<nsIFile> regDir;
329 rv = GetXULRunnerDir(argv[0], getter_AddRefs(regDir));
330 if (NS_FAILED(rv))
331 return 2;
333 return RegisterXULRunner(registerGlobal, regDir,
334 kGREProperties,
335 NS_ARRAY_LENGTH(kGREProperties),
336 milestone.get()) ? 0 : 2;
339 registerGlobal = IsArg(argv[1], "unregister-global");
340 registerUser = IsArg(argv[1], "unregister-user");
341 if (registerGlobal || registerUser) {
342 if (argc != 2) {
343 Usage(argv[0]);
344 return 1;
347 nsCOMPtr<nsIFile> regDir;
348 rv = GetXULRunnerDir(argv[0], getter_AddRefs(regDir));
349 if (NS_FAILED(rv))
350 return 2;
352 UnregisterXULRunner(registerGlobal, regDir, milestone.get());
353 return 0;
356 if (IsArg(argv[1], "find-gre")) {
357 if (argc != 3) {
358 Usage(argv[0]);
359 return 1;
362 char path[MAXPATHLEN];
363 static const GREVersionRange vr = {
364 argv[2], PR_TRUE,
365 argv[2], PR_TRUE
367 static const GREProperty kProperties[] = {
368 { "xulrunner", "true" }
371 rv = GRE_GetGREPathWithProperties(&vr, 1, kProperties,
372 NS_ARRAY_LENGTH(kProperties),
373 path, sizeof(path));
374 if (NS_FAILED(rv))
375 return 1;
377 printf("%s\n", path);
378 return 0;
381 if (IsArg(argv[1], "gre-version")) {
382 if (argc != 2) {
383 Usage(argv[0]);
384 return 1;
387 printf("%s\n", milestone.get());
388 return 0;
391 if (IsArg(argv[1], "install-app")) {
392 if (argc < 3 || argc > 5) {
393 Usage(argv[0]);
394 return 1;
397 char *appLocation = argv[2];
399 char *installTo = nsnull;
400 if (argc > 3) {
401 installTo = argv[3];
402 if (!*installTo) // left blank?
403 installTo = nsnull;
406 char *leafName = nsnull;
407 if (argc > 4) {
408 leafName = argv[4];
409 if (!*leafName)
410 leafName = nsnull;
413 nsCOMPtr<nsIFile> regDir;
414 rv = GetXULRunnerDir(argv[0], getter_AddRefs(regDir));
415 if (NS_FAILED(rv))
416 return 2;
418 return InstallXULApp(regDir, appLocation, installTo, leafName);
422 const char *appDataFile = PR_GetEnv("XUL_APP_FILE");
424 if (!(appDataFile && *appDataFile)) {
425 if (argc < 2) {
426 Usage(argv[0]);
427 return 1;
430 if (IsArg(argv[1], "app")) {
431 if (argc == 2) {
432 Usage(argv[0]);
433 return 1;
435 argv[1] = argv[0];
436 ++argv;
437 --argc;
440 appDataFile = argv[1];
441 argv[1] = argv[0];
442 ++argv;
443 --argc;
445 static char kAppEnv[MAXPATHLEN];
446 PR_snprintf(kAppEnv, MAXPATHLEN, "XUL_APP_FILE=%s", appDataFile);
447 PR_SetEnv(kAppEnv);
450 nsCOMPtr<nsILocalFile> appDataLF;
451 nsresult rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appDataLF));
452 if (NS_FAILED(rv)) {
453 Output(PR_TRUE, "Error: unrecognized application.ini path.\n");
454 return 2;
457 AutoAppData appData(appDataLF);
458 if (!appData) {
459 Output(PR_TRUE, "Error: couldn't parse application.ini.\n");
460 return 2;
463 return XRE_main(argc, argv, appData);