nsGNOMEShellService.cpp
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  * http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  *
15  * The Original Code is Shell Service.
16  *
17  * The Initial Developer of the Original Code is mozilla.org.
18  * Portions created by the Initial Developer are Copyright (C) 2004
19  * the Initial Developer. All Rights Reserved.
20  *
21  * Contributor(s):
22  *
23  * Alternatively, the contents of this file may be used under the terms of
24  * either the GNU General Public License Version 2 or later (the "GPL"), or
25  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26  * in which case the provisions of the GPL or the LGPL are applicable instead
27  * of those above. If you wish to allow use of your version of this file only
28  * under the terms of either the GPL or the LGPL, and not to allow others to
29  * use your version of this file under the terms of the MPL, indicate your
30  * decision by deleting the provisions above and replace them with the notice
31  * and other provisions required by the GPL or the LGPL. If you do not delete
32  * the provisions above, a recipient may use your version of this file under
33  * the terms of any one of the MPL, the GPL or the LGPL.
34  *
35  * ***** END LICENSE BLOCK ***** */
36 
37 #include "nsCOMPtr.h"
38 #include "nsGNOMEShellService.h"
39 #include "nsShellService.h"
40 #include "nsIServiceManager.h"
41 #include "nsILocalFile.h"
42 #include "nsIProperties.h"
43 #include "nsDirectoryServiceDefs.h"
44 #include "nsIPrefService.h"
45 #include "prenv.h"
46 #include "nsStringAPI.h"
47 #include "nsIGConfService.h"
48 #include "nsIGnomeVFSService.h"
49 #include "nsIStringBundle.h"
50 #include "nsIOutputStream.h"
51 #include "nsIProcess.h"
52 #include "nsNetUtil.h"
53 #include "nsIDOMHTMLImageElement.h"
54 #include "nsIImageLoadingContent.h"
55 #include "imgIRequest.h"
56 #include "imgIContainer.h"
57 #include "prprf.h"
58 #ifdef MOZ_WIDGET_GTK2
59 #include "nsIImageToPixbuf.h"
60 #endif
61 
62 #include <glib.h>
63 #include <glib-object.h>
64 #include <gtk/gtk.h>
65 #include <gdk/gdk.h>
66 #include <gdk-pixbuf/gdk-pixbuf.h>
67 #include <limits.h>
68 #include <stdlib.h>
69 
71 {
72  const char *name;
73  PRBool essential;
74 };
75 
77 {
78  const char *mimeType;
79  const char *extensions;
80 };
81 
83  { "http", PR_TRUE },
84  { "https", PR_TRUE },
85  { "ftp", PR_FALSE },
86  { "chrome", PR_FALSE }
87 };
88 
89 static const MimeTypeAssociation appTypes[] = {
90  { "text/html", "htm html shtml" },
91  { "application/xhtml+xml", "xhtml xht" }
92 };
93 
94 static const char kDocumentIconPath[] = "firefox-document.png";
95 
96 // GConf registry key constants
97 #define DG_BACKGROUND "/desktop/gnome/background"
98 
99 static const char kDesktopImageKey[] = DG_BACKGROUND "/picture_filename";
100 static const char kDesktopOptionsKey[] = DG_BACKGROUND "/picture_options";
101 static const char kDesktopDrawBGKey[] = DG_BACKGROUND "/draw_background";
102 static const char kDesktopColorKey[] = DG_BACKGROUND "/primary_color";
103 
104 nsresult
106 {
107  nsresult rv;
108 
109  // GConf and GnomeVFS _must_ be available, or we do not allow
110  // CreateInstance to succeed.
111 
112  nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
113  nsCOMPtr<nsIGnomeVFSService> vfs =
114  do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
115 
116  if (!gconf || !vfs)
117  return NS_ERROR_NOT_AVAILABLE;
118 
119  // Check G_BROKEN_FILENAMES. If it's set, then filenames in glib use
120  // the locale encoding. If it's not set, they use UTF-8.
121  mUseLocaleFilenames = PR_GetEnv("G_BROKEN_FILENAMES") != nsnull;
122 
123  nsCOMPtr<nsIProperties> dirSvc
124  (do_GetService("@mozilla.org/file/directory_service;1"));
125  NS_ENSURE_TRUE(dirSvc, NS_ERROR_NOT_AVAILABLE);
126 
127  nsCOMPtr<nsILocalFile> appPath;
128  rv = dirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsILocalFile),
129  getter_AddRefs(appPath));
130  NS_ENSURE_SUCCESS(rv, rv);
131 
132  rv = appPath->AppendNative(NS_LITERAL_CSTRING(MOZ_APP_NAME));
133  NS_ENSURE_SUCCESS(rv, rv);
134 
135  return appPath->GetNativePath(mAppPath);
136 }
137 
139 
140 PRBool
141 nsGNOMEShellService::KeyMatchesAppName(const char *aKeyValue) const
142 {
143 
144  gchar *commandPath;
145  if (mUseLocaleFilenames) {
146  gchar *nativePath = g_filename_from_utf8(aKeyValue, -1, NULL, NULL, NULL);
147  if (!nativePath) {
148  NS_ERROR("Error converting path to filesystem encoding");
149  return PR_FALSE;
150  }
151 
152  commandPath = g_find_program_in_path(nativePath);
153  g_free(nativePath);
154  } else {
155  commandPath = g_find_program_in_path(aKeyValue);
156  }
157 
158  if (!commandPath)
159  return PR_FALSE;
160 
161  PRBool matches = mAppPath.Equals(commandPath);
162  g_free(commandPath);
163  return matches;
164 }
165 
166 NS_IMETHODIMP
167 nsGNOMEShellService::IsDefaultBrowser(PRBool aStartupCheck,
168  PRBool* aIsDefaultBrowser)
169 {
170  *aIsDefaultBrowser = PR_FALSE;
171  if (aStartupCheck)
172  mCheckedThisSession = PR_TRUE;
173 
174  nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
175 
176  PRBool enabled;
177  nsCAutoString handler;
178 
179  for (unsigned int i = 0; i < NS_ARRAY_LENGTH(appProtocols); ++i) {
180  if (!appProtocols[i].essential)
181  continue;
182 
183  handler.Truncate();
184  gconf->GetAppForProtocol(nsDependentCString(appProtocols[i].name),
185  &enabled, handler);
186 
187  // The string will be something of the form: [/path/to/]browser "%s"
188  // We want to remove all of the parameters and get just the binary name.
189 
190  gint argc;
191  gchar **argv;
192 
193  if (g_shell_parse_argv(handler.get(), &argc, &argv, NULL) && argc > 0) {
194  handler.Assign(argv[0]);
195  g_strfreev(argv);
196  }
197 
198  if (!KeyMatchesAppName(handler.get()) || !enabled)
199  return NS_OK; // the handler is disabled or set to another app
200  }
201 
202  *aIsDefaultBrowser = PR_TRUE;
203 
204  return NS_OK;
205 }
206 
207 NS_IMETHODIMP
208 nsGNOMEShellService::SetDefaultBrowser(PRBool aClaimAllTypes,
209  PRBool aForAllUsers)
210 {
211 #ifdef DEBUG
212  if (aForAllUsers)
213  NS_WARNING("Setting the default browser for all users is not yet supported");
214 #endif
215 
216  nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
217 
218  nsCAutoString schemeList;
219  nsCAutoString appKeyValue(mAppPath);
220  appKeyValue.Append(" \"%s\"");
221  unsigned int i;
222 
223  for (i = 0; i < NS_ARRAY_LENGTH(appProtocols); ++i) {
224  schemeList.Append(nsDependentCString(appProtocols[i].name));
225  schemeList.Append(',');
226 
227  if (appProtocols[i].essential || aClaimAllTypes) {
228  gconf->SetAppForProtocol(nsDependentCString(appProtocols[i].name),
229  appKeyValue);
230  }
231  }
232 
233  if (aClaimAllTypes) {
234  nsCOMPtr<nsIGnomeVFSService> vfs =
235  do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
236 
237  nsCOMPtr<nsIStringBundleService> bundleService =
238  do_GetService(NS_STRINGBUNDLE_CONTRACTID);
239  NS_ENSURE_TRUE(bundleService, NS_ERROR_OUT_OF_MEMORY);
240 
241  nsCOMPtr<nsIStringBundle> brandBundle;
242  bundleService->CreateBundle(BRAND_PROPERTIES, getter_AddRefs(brandBundle));
243  NS_ENSURE_TRUE(brandBundle, NS_ERROR_FAILURE);
244 
245  nsString brandShortName, brandFullName;
246  brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
247  getter_Copies(brandShortName));
248  brandBundle->GetStringFromName(NS_LITERAL_STRING("brandFullName").get(),
249  getter_Copies(brandFullName));
250 
251  // use brandShortName as the application id.
252  NS_ConvertUTF16toUTF8 id(brandShortName);
253 
254  vfs->SetAppStringKey(id, nsIGnomeVFSService::APP_KEY_COMMAND, mAppPath);
255  vfs->SetAppStringKey(id, nsIGnomeVFSService::APP_KEY_NAME,
256  NS_ConvertUTF16toUTF8(brandFullName));
257 
258  // We don't want to be the default handler for "file:", but we do
259  // want Nautilus to know that we support file: if the MIME type is
260  // one that we can handle.
261 
262  schemeList.Append("file");
263 
264  vfs->SetAppStringKey(id, nsIGnomeVFSService::APP_KEY_SUPPORTED_URI_SCHEMES,
265  schemeList);
266 
267  vfs->SetAppStringKey(id, nsIGnomeVFSService::APP_KEY_EXPECTS_URIS,
268  NS_LITERAL_CSTRING("true"));
269 
270  vfs->SetAppBoolKey(id, nsIGnomeVFSService::APP_KEY_CAN_OPEN_MULTIPLE,
271  PR_FALSE);
272 
273  vfs->SetAppBoolKey(id, nsIGnomeVFSService::APP_KEY_REQUIRES_TERMINAL,
274  PR_FALSE);
275 
276  // Copy icons/document.png to ~/.icons/firefox-document.png
277  nsCAutoString iconFilePath(mAppPath);
278  PRInt32 lastSlash = iconFilePath.RFindChar(PRUnichar('/'));
279  if (lastSlash == -1) {
280  NS_ERROR("no slash in executable path?");
281  } else {
282  iconFilePath.SetLength(lastSlash);
283  nsCOMPtr<nsILocalFile> iconFile;
284  NS_NewNativeLocalFile(iconFilePath, PR_FALSE, getter_AddRefs(iconFile));
285  if (iconFile) {
286  iconFile->AppendRelativeNativePath(NS_LITERAL_CSTRING("icons/document.png"));
287 
288  nsCOMPtr<nsILocalFile> userIconPath;
289  NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")), PR_FALSE,
290  getter_AddRefs(userIconPath));
291  if (userIconPath) {
292  userIconPath->AppendNative(NS_LITERAL_CSTRING(".icons"));
293  iconFile->CopyToNative(userIconPath,
294  nsDependentCString(kDocumentIconPath));
295  }
296  }
297  }
298 
299  for (i = 0; i < NS_ARRAY_LENGTH(appTypes); ++i) {
300  vfs->AddMimeType(id, nsDependentCString(appTypes[i].mimeType));
301  vfs->SetMimeExtensions(nsDependentCString(appTypes[i].mimeType),
302  nsDependentCString(appTypes[i].extensions));
303  vfs->SetAppForMimeType(nsDependentCString(appTypes[i].mimeType), id);
304  vfs->SetIconForMimeType(nsDependentCString(appTypes[i].mimeType),
305  NS_LITERAL_CSTRING(kDocumentIconPath));
306  }
307 
308  vfs->SyncAppRegistry();
309  }
310 
311  return NS_OK;
312 }
313 
314 NS_IMETHODIMP
315 nsGNOMEShellService::GetShouldCheckDefaultBrowser(PRBool* aResult)
316 {
317  // If we've already checked, the browser has been started and this is a
318  // new window open, and we don't want to check again.
319  if (mCheckedThisSession) {
320  *aResult = PR_FALSE;
321  return NS_OK;
322  }
323 
324  nsCOMPtr<nsIPrefBranch> prefs;
325  nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
326  if (pserve)
327  pserve->GetBranch("", getter_AddRefs(prefs));
328 
329  if (prefs)
330  prefs->GetBoolPref(PREF_CHECKDEFAULTBROWSER, aResult);
331 
332  return NS_OK;
333 }
334 
335 NS_IMETHODIMP
336 nsGNOMEShellService::SetShouldCheckDefaultBrowser(PRBool aShouldCheck)
337 {
338  nsCOMPtr<nsIPrefBranch> prefs;
339  nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
340  if (pserve)
341  pserve->GetBranch("", getter_AddRefs(prefs));
342 
343  if (prefs)
344  prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck);
345 
346  return NS_OK;
347 }
348 
349 static nsresult
350 WriteImage(const nsCString& aPath, imgIContainer* aImage)
351 {
352 #ifndef MOZ_WIDGET_GTK2
353  return NS_ERROR_NOT_AVAILABLE;
354 #else
355  nsCOMPtr<nsIImageToPixbuf> imgToPixbuf =
356  do_GetService("@mozilla.org/widget/image-to-gdk-pixbuf;1");
357  if (!imgToPixbuf)
358  return NS_ERROR_NOT_AVAILABLE;
359 
360  GdkPixbuf* pixbuf = imgToPixbuf->ConvertImageToPixbuf(aImage);
361  if (!pixbuf)
362  return NS_ERROR_NOT_AVAILABLE;
363 
364  gboolean res = gdk_pixbuf_save(pixbuf, aPath.get(), "png", NULL, NULL);
365 
366  g_object_unref(pixbuf);
367  return res ? NS_OK : NS_ERROR_FAILURE;
368 #endif
369 }
370 
371 NS_IMETHODIMP
372 nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement,
373  PRInt32 aPosition)
374 {
375  nsresult rv;
376  nsCOMPtr<nsIImageLoadingContent> imageContent = do_QueryInterface(aElement, &rv);
377  if (!imageContent) return rv;
378 
379  // get the image container
380  nsCOMPtr<imgIRequest> request;
381  rv = imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
382  getter_AddRefs(request));
383  if (!request) return rv;
384  nsCOMPtr<imgIContainer> container;
385  rv = request->GetImage(getter_AddRefs(container));
386  if (!container) return rv;
387 
388  // Write the background file to the home directory.
389  nsCAutoString filePath(PR_GetEnv("HOME"));
390 
391  // get the product brand name from localized strings
392  nsString brandName;
393  nsCID bundleCID = NS_STRINGBUNDLESERVICE_CID;
394  nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(bundleCID));
395  if (bundleService) {
396  nsCOMPtr<nsIStringBundle> brandBundle;
397  rv = bundleService->CreateBundle(BRAND_PROPERTIES,
398  getter_AddRefs(brandBundle));
399  if (NS_SUCCEEDED(rv) && brandBundle) {
400  rv = brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
401  getter_Copies(brandName));
402  NS_ENSURE_SUCCESS(rv, rv);
403  }
404  }
405 
406  // build the file name
407  filePath.Append('/');
408  filePath.Append(NS_ConvertUTF16toUTF8(brandName));
409  filePath.Append("_wallpaper.png");
410 
411  // write the image to a file in the home dir
412  rv = WriteImage(filePath, container);
413 
414  // if the file was written successfully, set it as the system wallpaper
415  nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
416 
417  nsCAutoString options;
418  if (aPosition == BACKGROUND_TILE)
419  options.Assign("wallpaper");
420  else if (aPosition == BACKGROUND_STRETCH)
421  options.Assign("stretched");
422  else
423  options.Assign("centered");
424 
425  gconf->SetString(NS_LITERAL_CSTRING(kDesktopOptionsKey), options);
426 
427  // Set the image to an empty string first to force a refresh
428  // (since we could be writing a new image on top of an existing
429  // Firefox_wallpaper.png and nautilus doesn't monitor the file for changes)
430  gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey),
431  EmptyCString());
432 
433  gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), filePath);
434  gconf->SetBool(NS_LITERAL_CSTRING(kDesktopDrawBGKey), PR_TRUE);
435 
436  return rv;
437 }
438 
439 #define COLOR_16_TO_8_BIT(_c) ((_c) >> 8)
440 #define COLOR_8_TO_16_BIT(_c) ((_c) << 8 | (_c))
441 
442 NS_IMETHODIMP
443 nsGNOMEShellService::GetDesktopBackgroundColor(PRUint32 *aColor)
444 {
445  nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
446 
447  nsCAutoString background;
448  gconf->GetString(NS_LITERAL_CSTRING(kDesktopColorKey), background);
449 
450  if (background.IsEmpty()) {
451  *aColor = 0;
452  return NS_OK;
453  }
454 
455  GdkColor color;
456  gboolean success = gdk_color_parse(background.get(), &color);
457 
458  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
459 
460  *aColor = COLOR_16_TO_8_BIT(color.red) << 16 |
461  COLOR_16_TO_8_BIT(color.green) << 8 |
462  COLOR_16_TO_8_BIT(color.blue);
463  return NS_OK;
464 }
465 
466 static void
467 ColorToCString(PRUint32 aColor, nsCString& aResult)
468 {
469  // The #rrrrggggbbbb format is used to match gdk_color_to_string()
470  char *buf = aResult.BeginWriting(13);
471  if (!buf)
472  return;
473 
474  PRUint16 red = COLOR_8_TO_16_BIT((aColor >> 16) & 0xff);
475  PRUint16 green = COLOR_8_TO_16_BIT((aColor >> 8) & 0xff);
476  PRUint16 blue = COLOR_8_TO_16_BIT(aColor & 0xff);
477 
478  PR_snprintf(buf, 14, "#%04x%04x%04x", red, green, blue);
479 }
480 
481 NS_IMETHODIMP
482 nsGNOMEShellService::SetDesktopBackgroundColor(PRUint32 aColor)
483 {
484  NS_ASSERTION(aColor <= 0xffffff, "aColor has extra bits");
485  nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
486 
487  nsCAutoString colorString;
488  ColorToCString(aColor, colorString);
489 
490  gconf->SetString(NS_LITERAL_CSTRING(kDesktopColorKey), colorString);
491 
492  return NS_OK;
493 }
494 
495 NS_IMETHODIMP
496 nsGNOMEShellService::OpenApplication(PRInt32 aApplication)
497 {
498  nsCAutoString scheme;
499  if (aApplication == APPLICATION_MAIL)
500  scheme.Assign("mailto");
501  else if (aApplication == APPLICATION_NEWS)
502  scheme.Assign("news");
503  else
504  return NS_ERROR_NOT_AVAILABLE;
505 
506  nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
507 
508  PRBool enabled;
509  nsCAutoString appCommand;
510  gconf->GetAppForProtocol(scheme, &enabled, appCommand);
511 
512  if (!enabled)
513  return NS_ERROR_FAILURE;
514 
515  // XXX we don't currently handle launching a terminal window.
516  // If the handler requires a terminal, bail.
517  PRBool requiresTerminal;
518  gconf->HandlerRequiresTerminal(scheme, &requiresTerminal);
519  if (requiresTerminal)
520  return NS_ERROR_FAILURE;
521 
522  // Perform shell argument expansion
523  int argc;
524  char **argv;
525  if (!g_shell_parse_argv(appCommand.get(), &argc, &argv, NULL))
526  return NS_ERROR_FAILURE;
527 
528  char **newArgv = new char*[argc + 1];
529  int newArgc = 0;
530 
531  // Run through the list of arguments. Copy all of them to the new
532  // argv except for %s, which we skip.
533  for (int i = 0; i < argc; ++i) {
534  if (strcmp(argv[i], "%s") != 0)
535  newArgv[newArgc++] = argv[i];
536  }
537 
538  newArgv[newArgc] = nsnull;
539 
540  gboolean err = g_spawn_async(NULL, newArgv, NULL, G_SPAWN_SEARCH_PATH,
541  NULL, NULL, NULL, NULL);
542 
543  g_strfreev(argv);
544  delete[] newArgv;
545 
546  return err ? NS_OK : NS_ERROR_FAILURE;
547 }
548 
549 NS_IMETHODIMP
550 nsGNOMEShellService::OpenApplicationWithURI(nsILocalFile* aApplication, const nsACString& aURI)
551 {
552  nsresult rv;
553  nsCOMPtr<nsIProcess> process =
554  do_CreateInstance("@mozilla.org/process/util;1", &rv);
555  if (NS_FAILED(rv))
556  return rv;
557 
558  rv = process->Init(aApplication);
559  if (NS_FAILED(rv))
560  return rv;
561 
562  const nsCString spec(aURI);
563  const char* specStr = spec.get();
564  return process->Run(PR_FALSE, &specStr, 1);
565 }
566 
567 NS_IMETHODIMP
568 nsGNOMEShellService::GetDefaultFeedReader(nsILocalFile** _retval)
569 {
570  return NS_ERROR_NOT_IMPLEMENTED;
571 }
#define COLOR_16_TO_8_BIT(_c)
NS_DECL_ISUPPORTS NS_DECL_NSISHELLSERVICE nsresult Init() NS_HIDDEN
return NS_OK
_updateCookies aPath
const long APPLICATION_NEWS
var dirSvc
static const char kDocumentIconPath[]
static const char kDesktopDrawBGKey[]
menuItem id
Definition: FeedWriter.js:971
const long APPLICATION_MAIL
NS_IMPL_ISUPPORTS1(sbDeviceCapabilitiesUtils, sbIDeviceCapabilitiesUtils) sbDeviceCapabilitiesUtils
const NS_PREFSERVICE_CONTRACTID
#define COLOR_8_TO_16_BIT(_c)
#define PREF_CHECKDEFAULTBROWSER
const long BACKGROUND_TILE
#define DG_BACKGROUND
#define BRAND_PROPERTIES
static const char kDesktopColorKey[]
static const char kDesktopOptionsKey[]
static const ProtocolAssociation appProtocols[]
var prefs
Definition: FeedWriter.js:1169
foldersync options
Definition: options.js:13
static const MimeTypeAssociation appTypes[]
static void ColorToCString(PRUint32 aColor, nsCString &aResult)
_getSelectedPageStyle s i
var brandBundle
Definition: xpInstallHat.js:37
GstMessage gpointer data sbGStreamerMessageHandler * handler
static const char kDesktopImageKey[]
static nsresult WriteImage(const nsCString &aPath, imgIContainer *aImage)
const long BACKGROUND_STRETCH